{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4b77cee9-c119-4239-a4dd-2430f1900322",
   "metadata": {},
   "source": [
    "# 实验二、三"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8cbeb8d-b5be-4f92-b911-ea045d13baf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd # To load house price data\n",
    "import numpy as np # To manipulate data\n",
    "\n",
    "# Load from URL\n",
    "# data_url = 'http://lib.stat.cmu.edu/datasets/boston' # Set url of the dataset\n",
    "# raw_df = pd.read_csv(data_url, sep='\\s+', skiprows=22, header=None) # Load data\n",
    "\n",
    "# Load from local file\n",
    "data_url = './Data/houseprice.csv' # Set url of the dataset\n",
    "raw_df = pd.read_csv(data_url, sep=',', skiprows=1, header=None) # Load data\n",
    "\n",
    "raw_df.head(10) # Display the raw data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "551c2cdf-582c-450a-b051-8b7735ca3685",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "from matplotlib import font_manager\n",
    "\n",
    "font_manager.fontManager.addfont('./Data/simhei.ttf') # Add the font\n",
    "matplotlib.rc('font', family='SimHei') # Set the font\n",
    "import matplotlib.pyplot as plt # To draw figures\n",
    "\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']  # Support Chinese\n",
    "plt.rcParams['axes.unicode_minus'] = False  # Support negative sign\n",
    "\n",
    "num_fts = data.shape[1] # Get the number of features\n",
    "num_col = 6 # Number of columns in the figure\n",
    "num_row = int(np.ceil(num_fts / num_col)) # Number of rows in the figure\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "_, axes = plt.subplots(num_row, num_col, figsize=(18, 3*num_row)) # Create a figure\n",
    "\n",
    "for i in range(num_fts): # Loop through all features\n",
    "    row = int(i / num_col) # Get the row index\n",
    "    col = i % num_col # Get the column index\n",
    "\n",
    "    ax = axes[row, col]\n",
    "    ax.scatter(data[:, i], target) # Plot scatter fig of i-th feature and target\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size) # Set tick label size\n",
    "    ax.set_xlabel(fts_names[i], fontsize=label_size) # Label the x-axis\n",
    "    ax.set_ylabel('房价中位数（千美元）', fontsize=label_size) # Label the y-axis\n",
    "\n",
    "plt.tight_layout() # Adjust the layout of the figure\n",
    "plt.savefig('1.png', dpi=300)\n",
    "plt.show() # Display the figure\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a06fdb96-76fb-4ef7-9e73-ade70ad85489",
   "metadata": {},
   "outputs": [],
   "source": [
    "def linear_fun(x, w, b):\n",
    "    '''\n",
    "    This a linear prediction function.\n",
    "    x: feature\n",
    "    b: bias\n",
    "    w: weight\n",
    "    '''\n",
    "\n",
    "    y = w * x + b\n",
    "\n",
    "    return y\n",
    "\n",
    "fig, ax, x_linear = draw_scatter(x, y) # Plot the scatter\n",
    "\n",
    "ax.plot(x_linear, linear_fun(x_linear, 1, 4), color='green', linewidth=2) # y = x + 4\n",
    "# plt.savefig('room_price_f1.png', dpi=300) # Make figure clearer\n",
    "\n",
    "ax.plot(x_linear, linear_fun(x_linear, 6, -4), color='orange', linewidth=2) # y = 6x - 4\n",
    "# plt.savefig('room_price_f2.png', dpi=300) # Make figure clearer\n",
    "\n",
    "ax.plot(x_linear, linear_fun(x_linear, 11, -47), color='red', linewidth=2) # y = 11x - 47\n",
    "# plt.savefig('room_price_f3.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('3.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28067977-1c39-4403-a863-c59d09a9479f",
   "metadata": {},
   "outputs": [],
   "source": [
    "def nonlinear_fun(x, w, b):\n",
    "    '''\n",
    "    This an example of non-linear prediction function.\n",
    "    x: feature\n",
    "    b: bias\n",
    "    w: weight\n",
    "\n",
    "    Return:\n",
    "    y: prediction\n",
    "    '''\n",
    "    return w / x + b\n",
    "\n",
    "\n",
    "fig, ax, x_linear = draw_scatter(x, y) # Plot the scatter\n",
    "ax.plot(x_linear, nonlinear_fun(x_linear, 100, 10), color='red', linewidth=2) # 100 / x + 10\n",
    "plt.savefig('4.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c2dee940-7c4b-44d4-a69b-d36f95c3a539",
   "metadata": {},
   "outputs": [],
   "source": [
    "w_min, w_max = -200, 200 # Weight range\n",
    "b_min, b_max = -200, 200 # Bias range\n",
    "param_num = 800 # Number of per parameter\n",
    "\n",
    "w_list = np.linspace(w_min, w_max, param_num) # Create a sequence of w\n",
    "b_list = np.linspace(b_min, b_max, param_num) # Create a sequence of b\n",
    "\n",
    "w_grid, b_grid = np.meshgrid(w_list, b_list) # Create a grid of w and b\n",
    "loss_grid = np.zeros((param_num, param_num)) # Create a grid of loss\n",
    "\n",
    "for i in range(param_num):\n",
    "    for j in range(param_num):\n",
    "        # Compute loss\n",
    "        y_pred = linear_fun(x, w_grid[i, j], b_grid[i, j])\n",
    "        loss_temp = np.mean((y_pred - y) ** 2) / 2\n",
    "        loss_grid[i, j] = loss_temp / 10 ** 5 # Scale loss for display"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99cb8d12-f5e0-4c52-8b22-6e3728c4bf78",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Draw heatmap first\n",
    "def draw_heatmap(w_grid, b_grid, loss_grid):\n",
    "    '''\n",
    "    Display training process of w and b\n",
    "    '''\n",
    "    global label_size, ticklabel_size # Set global variables of font size\n",
    "\n",
    "    w_min, w_max = -200, 200\n",
    "    b_min, b_max = -200, 200\n",
    "\n",
    "    # Set figure\n",
    "    fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "    # Plot the loss\n",
    "    im = ax.imshow(loss_grid, extent=[w_min, w_max, b_min, b_max], origin='lower', cmap='viridis', zorder=0)\n",
    "\n",
    "    # Set x-axis and y-axis\n",
    "    ax.set_xticks(np.linspace(w_min, w_max, 5))\n",
    "    ax.set_xticklabels(np.linspace(w_min, w_max, 5))\n",
    "    ax.set_yticks(np.linspace(b_min, b_max, 5)[1:])\n",
    "    ax.set_yticklabels(np.linspace(b_min, b_max, 5)[1:])\n",
    "    ax.set_xlabel('Weight (w)', fontsize=label_size)\n",
    "    ax.set_ylabel('Bias (b)', fontsize=label_size)\n",
    "\n",
    "    ax.set_xlim(w_min, w_max)\n",
    "    ax.set_ylim(b_min, b_max)\n",
    "\n",
    "    ax.set_position([0.15, 0.13, 0.60, 0.8]) # Set the position of the figure\n",
    "\n",
    "    # Set tick label size\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "    # Mark the point of lowest loss\n",
    "    min_loss_idx = np.unravel_index(np.argmin(loss_grid), loss_grid.shape)\n",
    "    min_w = w_grid[min_loss_idx]\n",
    "    min_b = b_grid[min_loss_idx]\n",
    "    ax.scatter(min_w, min_b, color='red', marker='x', linewidth=5, s=12**2)\n",
    "\n",
    "    return fig, ax\n",
    "\n",
    "fig, ax = draw_heatmap(w_grid, b_grid, loss_grid)\n",
    "\n",
    "# plt.savefig('loss_with_mark.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('5.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d26b99a-8c5d-476c-a88a-fb5f802b49c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def loss_w_base():\n",
    "    '''\n",
    "    Draw the baseline of loss function when b is -34.67\n",
    "    '''\n",
    "    global label_size, ticklabel_size # Set global variables of font size\n",
    "\n",
    "    b = -34.67\n",
    "\n",
    "    w_min, w_max = -200, 200 # Weight range\n",
    "    param_num = 10000 # Number of per parameter\n",
    "\n",
    "    w_base = np.linspace(w_min, w_max, param_num) # Create a sequence of w\n",
    "\n",
    "    loss_base = np.zeros(param_num) # Create a grid of loss\n",
    "\n",
    "    for i in range(param_num):\n",
    "        # Compute loss\n",
    "        y_pred = linear_fun(x, w_base[i], b)\n",
    "        loss_base[i] = np.mean((y_pred - y) ** 2) / 2\n",
    "\n",
    "    fig, ax = plt.subplots(figsize=(10,6))\n",
    "    ax.plot(w_base, loss_base / 10 ** 5, color='black', linewidth=2, zorder=0) # Scale loss for display\n",
    "    ax.set_xlim(-210, 210)\n",
    "    ax.set_ylim(-0.2, 10)\n",
    "    ax.set_xlabel('Weight', fontsize=label_size)\n",
    "    ax.set_ylabel('Loss ($x10^5$)', fontsize=label_size)\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "    return fig, ax\n",
    "\n",
    "fig, ax = loss_w_base()\n",
    "# plt.savefig('learning_rate_base.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('7.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "370c1c0f-4874-4ccd-a45a-34b770f09631",
   "metadata": {},
   "outputs": [],
   "source": [
    "lr = 0.000001 # Set learning rate\n",
    "\n",
    "w_list, loss_list = learn_w(x, y, lr) # Training model\n",
    "fig, ax = loss_w_base() # Draw base losses\n",
    "ax.plot(w_list, loss_list, color='blue', marker='.', markersize=10, linewidth=2, zorder=1) # Plot training losses\n",
    "ax.scatter(w_list[-1], loss_list[-1], s=15**2, marker='*', facecolor='white', edgecolor='blue', linewidth=2, zorder=2)\n",
    "\n",
    "# plt.savefig('learning_rate_D000001.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('8.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a23c0c6-3e68-477f-80cd-abe26ef08fca",
   "metadata": {},
   "outputs": [],
   "source": [
    "lr = 0.0000001 # Set learning rate\n",
    "\n",
    "w_list, loss_list = learn_w(x, y, lr) # Training model\n",
    "fig, ax = loss_w_base() # Draw base losses\n",
    "ax.plot(w_list, loss_list, color='blue', marker='.', markersize=10, linewidth=2, zorder=1) # Plot training losses\n",
    "ax.scatter(w_list[-1], loss_list[-1], s=15**2, marker='*', facecolor='white', edgecolor='blue', linewidth=2, zorder=2)\n",
    "\n",
    "# plt.savefig('learning_rate_D0000001.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('9.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97c677af-f047-4ce6-a08f-f7e8bc63cd69",
   "metadata": {},
   "outputs": [],
   "source": [
    "lr = 0.0001 # Set learning rate\n",
    "\n",
    "w_list, loss_list = learn_w(x, y, lr) # Training model\n",
    "fig, ax = loss_w_base() # Draw base losses\n",
    "ax.plot(w_list, loss_list, color='blue', marker='.', markersize=10, linewidth=2, zorder=1) # Plot training losses\n",
    "ax.scatter(w_list[-1], loss_list[-1], s=15**2, marker='*', facecolor='white', edgecolor='blue', linewidth=2, zorder=2)\n",
    "\n",
    "# plt.savefig('learning_rate_D0001.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('10.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78506489-6116-4e41-a398-7ed549af7b79",
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_loss_and_derivative(x, y, w, b):\n",
    "    '''\n",
    "    This a linear prediction function.\n",
    "\n",
    "    Return loss, dw, db:\n",
    "    loss: loss of the prediction\n",
    "    dw: partial derivative of w\n",
    "    db: partial derivative of b\n",
    "    '''\n",
    "    pass\n",
    "\n",
    "def init_param():\n",
    "    '''\n",
    "    This a linear prediction function.\n",
    "\n",
    "    Return w, b:\n",
    "    w: weight\n",
    "    b: bias\n",
    "    '''\n",
    "    pass\n",
    "\n",
    "def train_linear_fun(x, y, lr, num_iter):\n",
    "    '''\n",
    "    This a linear prediction function.\n",
    "\n",
    "    Return training log including losses and parameters:\n",
    "    loss_list: list of losses\n",
    "    param_list: list of parameters\n",
    "    '''\n",
    "    pass\n",
    "\n",
    "# Training models in different conditions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96eeb34b-8e30-4d57-a830-6b4549e00913",
   "metadata": {},
   "outputs": [],
   "source": [
    "def learn_w_b(x, y, lr=0.0001, max_epoch=100000, batch_size=4, adagrad=False):\n",
    "    '''\n",
    "    Learning weight w and bias b\n",
    "    (w, b) starts with (-200, -200)\n",
    "\n",
    "    Return:\n",
    "    w_list: array of w\n",
    "    b_list: array of b\n",
    "    loss_final: final loss\n",
    "    '''\n",
    "    # Initialize parameters\n",
    "    w, b = -200, -200\n",
    "\n",
    "    if adagrad == True:\n",
    "        lr_w = 0.0\n",
    "        lr_b = 0.0\n",
    "\n",
    "    # Model training process\n",
    "    w_list = [w] # Create a list to store w\n",
    "    b_list = [b] # Create a list to store b\n",
    "    for ie in range(max_epoch):\n",
    "        # Shuffle x\n",
    "        idx = np.random.permutation(x.shape[0])\n",
    "\n",
    "        # Split indices into batches\n",
    "        dw, db = 0, 0\n",
    "        for ib in range(0, x.shape[0], batch_size):\n",
    "            batch_idx = idx[ib:ib+batch_size]\n",
    "            x_batch = x[batch_idx]\n",
    "            y_batch = y[batch_idx]\n",
    "\n",
    "            y_batch_pred = linear_fun(x_batch, w, b)\n",
    "\n",
    "            dw = dw + np.mean((y_batch_pred - y_batch) * x_batch) # Compute partial derivative of w\n",
    "            db = db + np.mean((y_batch_pred - y_batch) * 1.0) # Compute partial derivative of b\n",
    "\n",
    "        if adagrad == True:\n",
    "            lr_w = lr_w + dw ** 2\n",
    "            lr_b = lr_b + db ** 2\n",
    "\n",
    "            w -= lr / np.sqrt(lr_w) * dw # Update w\n",
    "            b -= lr / np.sqrt(lr_b) * db # Update d\n",
    "\n",
    "        else:\n",
    "            w -= lr * dw # Update w\n",
    "            b -= lr * db # Update d\n",
    "\n",
    "        w_list.append(w)\n",
    "        b_list.append(b)\n",
    "\n",
    "    # Change list into array for plotting\n",
    "    w_list = np.array(w_list)\n",
    "    b_list = np.array(b_list)\n",
    "\n",
    "    # Final loss\n",
    "    y_pred = linear_fun(x, w, b)\n",
    "    loss_final = np.mean((y - y_pred) ** 2) / 2 # Compute and record loss\n",
    "\n",
    "    return w_list, b_list, loss_final\n",
    "\n",
    "w_list, b_list, loss_final = learn_w_b(x, y, lr=0.00001, max_epoch=10000)\n",
    "\n",
    "fig, ax = draw_heatmap(w_grid, b_grid, loss_grid) # Draw base image\n",
    "ax.plot(w_list, b_list, color='yellow', marker='.', linewidth=2, markersize=4, zorder=1) # Plot training losses\n",
    "ax.scatter(w_list[0], b_list[0], color='yellow', facecolor='black', marker='o', linewidth=2, s=12**2, zorder=2) # Add start place\n",
    "\n",
    "# plt.savefig('f2_learning_rate_D00001.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('6.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a0fa5ff-856c-4732-aaaa-b897facb9125",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "def normalization(x, norm_type='none'):\n",
    "    '''\n",
    "    Normalization\n",
    "    '''\n",
    "    if norm_type == 'min-max':\n",
    "        a, b = np.min(x), np.max(x)\n",
    "        x_norm = (x - a) / (b - a)\n",
    "\n",
    "    elif norm_type == 'z-score':\n",
    "        a, b = np.mean(x), np.std(x)\n",
    "        x_norm = (x - a) / b\n",
    "    \n",
    "    elif norm_type == 'none':\n",
    "        a, b = 0, 0\n",
    "        x_norm = x\n",
    "\n",
    "    return x_norm, a, b\n",
    "\n",
    "def norm_recover(x_norm, a, b, norm_type='none'):\n",
    "    '''\n",
    "    Normalization\n",
    "    '''\n",
    "    if norm_type == 'min-max':\n",
    "        x = x_norm * (b - a) + a\n",
    "\n",
    "    elif norm_type == 'z-score':\n",
    "        x = x_norm * b + a\n",
    "\n",
    "    elif norm_type == 'none':\n",
    "        x = x_norm\n",
    "\n",
    "    return x\n",
    "\n",
    "def draw_uniform_scatter(x, y, xlim, ylim):\n",
    "    '''\n",
    "    This a specific function to draw a scatter figure of room number and house price.\n",
    "    x: room number\n",
    "    y: house price\n",
    "    '''\n",
    "    global label_size, ticklabel_size # Set global variables of font size\n",
    "\n",
    "    fig, ax = plt.subplots() # Create a figure and a set of subplots.\n",
    "    ax.scatter(x, y) # Plot the data\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size) # Set tick label size\n",
    "    ax.set_xlabel('平均房间数', fontsize=label_size) # Label the x-axis\n",
    "    ax.set_ylabel('房价中位数（千美元）', fontsize=label_size) # Label the y-axis\n",
    "\n",
    "    ax.set_xlim(xlim[0], xlim[1]) # Set the x-axis limits\n",
    "    ax.set_ylim(ylim[0], ylim[1]) # Set the y-axis limits\n",
    "\n",
    "    ax.set_position([0.12, 0.14, 0.85, 0.83]) # Set the position of the figure\n",
    "\n",
    "    x_linear = np.linspace(xlim[0], xlim[1], 100) # Create a sequence of x to draw prediction function\n",
    "\n",
    "    return fig, ax, x_linear\n",
    "    \n",
    "norm_type = 'z-score'\n",
    "\n",
    "# Normalize x\n",
    "x_norm, x_a, x_b = normalization(x, norm_type=norm_type)\n",
    "\n",
    "# Split data into training and testing domains (Not for this section)\n",
    "X_train, X_test, Y_train, Y_test = train_test_split(x_norm, y, test_size=0.2, random_state=42)\n",
    "\n",
    "num_samples = 10\n",
    "np.random.seed(42) # Set the random seed for reproducibility\n",
    "random_indices = np.random.choice(X_train.shape[0], num_samples, replace=False)\n",
    "x_train = X_train[random_indices]\n",
    "y_train = Y_train[random_indices]\n",
    "\n",
    "random_indices = np.random.choice(X_test.shape[0], num_samples, replace=False)\n",
    "x_test = X_test[random_indices]\n",
    "y_test = Y_test[random_indices]\n",
    "\n",
    "x_test_scatter = norm_recover(x_test, x_a, x_b, norm_type=norm_type)\n",
    "\n",
    "# Plot the training data\n",
    "x_lim_offset = 0.1\n",
    "x_train_scatter = norm_recover(x_train, x_a, x_b, norm_type=norm_type)\n",
    "x_scatter_min = np.min([np.min(x_train_scatter), np.min(x_test_scatter)]) - x_lim_offset\n",
    "x_scatter_max = np.max([np.max(x_train_scatter), np.max(x_test_scatter)]) + x_lim_offset\n",
    "x_lim = [x_scatter_min, x_scatter_max]\n",
    "\n",
    "y_lim_offset = 1\n",
    "y_scatter_min = np.min([np.min(y_train), np.min(y_test)]) - y_lim_offset\n",
    "y_scatter_max = np.max([np.max(y_train), np.max(y_test)]) + y_lim_offset\n",
    "y_lim = [y_scatter_min, y_scatter_max]\n",
    "\n",
    "fig, ax, _ = draw_uniform_scatter(x_train_scatter, y_train, x_lim, y_lim)\n",
    "# plt.savefig(f'scatter_train_data_{num_samples}.png', dpi=300) # Make figure clearer\n",
    "plt.show()\n",
    "\n",
    "# Plot the testing data\n",
    "fig, ax, _ = draw_uniform_scatter(x_test_scatter, y_test, x_lim, y_lim)\n",
    "# plt.savefig(f'scatter_test_data_{num_samples}.png', dpi=300) # Make figure clearer\n",
    "plt.savefig('11.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e15a272b-bb2c-4f3e-b867-207f7c6a00e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_poly_mdl(x_tr, y_tr, x_te, y_te, lr=100, max_epoch=1000000, batch_size=1, p=0, regulization_method='none', regulization_lambda=0, disp=False, stop=False):\n",
    "    '''\n",
    "    Learning weight w and bias b\n",
    "    p is the order of polynomial\n",
    "\n",
    "    Return:\n",
    "    w_list: array of w\n",
    "    b_list: array of b\n",
    "    err_train: prediction accuracy\n",
    "    '''\n",
    "    global norm_type\n",
    "\n",
    "    # Train logs\n",
    "    logs = {}\n",
    "    logs['epoch_itr'] = []\n",
    "    logs['loss_train'] = []\n",
    "    logs['loss_test'] = []\n",
    "    logs['loss_batch'] = []\n",
    "    logs['err_train'] = []\n",
    "    logs['err_test'] = []\n",
    "\n",
    "    # Initialize w, b, and exponential x\n",
    "    b = 0.0\n",
    "    if p > 0:\n",
    "        w = np.random.randn(p)\n",
    "        \n",
    "        x_tr = [x_tr ** (i+1) for i in range(p)]\n",
    "        x_tr = np.array(x_tr).T\n",
    "        \n",
    "        x_te = [x_te ** (i+1) for i in range(p)]\n",
    "        x_te = np.array(x_te).T\n",
    "        \n",
    "    else:\n",
    "        w = np.random.randn(x_tr.shape[1])\n",
    "\n",
    "    # Initialize learning rate\n",
    "    lr_w = np.zeros(w.size)\n",
    "    lr_b = 0.0\n",
    "\n",
    "    # For early stop\n",
    "    min_err = 100000000\n",
    "    err_no_improvement = 0\n",
    "    early_stop = 100\n",
    "\n",
    "    # Model training process\n",
    "    itr_num = 0\n",
    "    for ie in range(max_epoch):\n",
    "\n",
    "        idx = np.random.permutation(x_tr.shape[0]) # Shuffle x\n",
    "\n",
    "        dw = np.zeros(w.size)\n",
    "        db = 0.0\n",
    "\n",
    "        for ib in range(0, x_tr.shape[0], batch_size):\n",
    "            batch_idx = idx[ib:ib+batch_size]\n",
    "            x_batch = x_tr[batch_idx, :]\n",
    "            y_batch = y_tr[batch_idx]\n",
    "\n",
    "            y_batch_pred = np.matmul(x_batch, w) + b\n",
    "            y_batch_diff = y_batch_pred - y_batch\n",
    "            \n",
    "            # Regularization in loss and gradient\n",
    "            if regulization_method == 'L1':\n",
    "                loss_reg = regulization_lambda * np.sum(np.abs(w))\n",
    "                grad_reg = regulization_lambda * np.sign(w)\n",
    "            elif regulization_method == 'L2':\n",
    "                loss_reg = regulization_lambda * np.sum(w ** 2) / 2\n",
    "                grad_reg = regulization_lambda * w\n",
    "            else:\n",
    "                loss_reg = 0.0\n",
    "                grad_reg = np.zeros(w.size)\n",
    "\n",
    "            logs['loss_batch'].append(np.mean(y_batch_diff ** 2) / 2 + loss_reg)\n",
    "\n",
    "            # Compute partial derivative of w and b\n",
    "            for i in range(w.size):\n",
    "                dw[i] = dw[i] + np.mean(y_batch_diff * x_batch[:, i]) + grad_reg[i]\n",
    "            db = db + np.mean(y_batch_diff * 1.0) # Compute partial derivative of b\n",
    "            \n",
    "            itr_num += 1\n",
    "\n",
    "        # Regularization in loss and gradient\n",
    "        if regulization_method == 'L1':\n",
    "            loss_reg = regulization_lambda * np.sum(np.abs(w))\n",
    "            \n",
    "        elif regulization_method == 'L2':\n",
    "            loss_reg = regulization_lambda * np.sum(w ** 2) / 2\n",
    "            \n",
    "        else:\n",
    "            loss_reg = 0\n",
    "        \n",
    "        # Compute epoch loss and err\n",
    "        y_tr_pred = np.matmul(x_tr, w) + b\n",
    "        y_tr_diff = y_tr_pred - y_tr\n",
    "        \n",
    "        loss_train = np.mean(y_tr_diff ** 2) / 2 + loss_reg\n",
    "        logs['loss_train'].append(loss_train)\n",
    "        \n",
    "        err_train = np.mean(np.abs(y_tr_diff))\n",
    "        logs['err_train'].append(err_train)\n",
    "                \n",
    "        y_te_pred = np.matmul(x_te, w) + b\n",
    "        y_te_diff = y_te_pred - y_te\n",
    "        \n",
    "        loss_test = np.mean(y_te_diff ** 2) / 2 + loss_reg\n",
    "        logs['loss_test'].append(loss_test)\n",
    "        \n",
    "        err_test = np.mean(np.abs(y_te_diff))\n",
    "        logs['err_test'].append(err_test)\n",
    "        \n",
    "        # Display training process\n",
    "        if (ie + 1) % 10000 == 0 and disp == True:\n",
    "            print(f'Epoch {ie+1}: train loss ({loss_train:.8f}), test loss ({loss_test:.8f}), train error ({err_train:.4f}), test error ({err_test:.4f})')\n",
    "        \n",
    "        # Early stop\n",
    "        if stop == True:\n",
    "            if err_test < min_err:\n",
    "                min_err = err_test\n",
    "                err_no_improvement = 0\n",
    "            else:\n",
    "                err_no_improvement += 1\n",
    "\n",
    "            if err_no_improvement >= early_stop:\n",
    "                break\n",
    "\n",
    "        # Adagrad\n",
    "        lr_w = lr_w + dw ** 2\n",
    "        lr_b = lr_b + db ** 2\n",
    "\n",
    "        w -= lr / np.sqrt(lr_w) * dw # Update w\n",
    "        b -= lr / np.sqrt(lr_b) * db # Update d\n",
    "\n",
    "    # Regularization in loss and gradient\n",
    "    if regulization_method == 'L1':\n",
    "        loss_reg = regulization_lambda * np.sum(np.abs(w))\n",
    "        \n",
    "    elif regulization_method == 'L2':\n",
    "        loss_reg = regulization_lambda * np.sum(w ** 2) / 2\n",
    "        \n",
    "    else:\n",
    "        loss_reg = 0\n",
    "\n",
    "    # Compute epoch loss and err\n",
    "    y_tr_pred = np.matmul(x_tr, w) + b\n",
    "    y_tr_diff = y_tr_pred - y_tr\n",
    "\n",
    "    loss_train = np.mean(y_tr_diff ** 2) / 2 + loss_reg\n",
    "    logs['loss_train'].append(loss_train)\n",
    "    \n",
    "    err_train = np.mean(np.abs(y_tr_diff))\n",
    "    logs['err_train'].append(err_train)\n",
    "            \n",
    "    y_te_pred = np.matmul(x_te, w) + b\n",
    "    y_te_diff = y_te_pred - y_te\n",
    "\n",
    "    loss_test = np.mean(y_te_diff ** 2) / 2 + loss_reg\n",
    "    logs['loss_test'].append(loss_test)\n",
    "    \n",
    "    err_test = np.mean(np.abs(y_te_diff))\n",
    "    logs['err_test'].append(err_test)\n",
    "    \n",
    "    # Change logs to array\n",
    "    logs['loss_train'] = np.array(logs['loss_train'])\n",
    "    logs['err_train'] = np.array(logs['err_train'])\n",
    "    logs['loss_test'] = np.array(logs['loss_test'])\n",
    "    logs['err_test'] = np.array(logs['err_test'])\n",
    "\n",
    "    return w, b, logs\n",
    "\n",
    "p_list = range(1, 11, 1) # Set the order of polynomial\n",
    "param_list = []\n",
    "err_list = []\n",
    "\n",
    "for p in p_list:\n",
    "    # Train model\n",
    "    w, b, logs = train_poly_mdl(x_train, y_train, x_test, y_test, p=p, lr=100, max_epoch=10000, batch_size=num_samples)\n",
    "    param_list.append((w, b))\n",
    "\n",
    "    err_train = logs['err_train'][-1]\n",
    "    err_test = logs['err_test'][-1]\n",
    "    err_list.append((err_train, err_test))\n",
    "\n",
    "    print(f'p={p}\\t Training avg_err: {err_train}\\t Testing avg_err: {err_test}')\n",
    "\n",
    "err_list = np.array(err_list)\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "plt.plot(p_list, err_list[:, 0], color='blue', marker='.', markersize=10, linewidth=2, zorder=1, label='训练集') # Plot training losses\n",
    "plt.plot(p_list, err_list[:, 1], color='red', marker='.', markersize=10, linewidth=2, zorder=1, label='测试集') # Plot training losses\n",
    "plt.legend(ncol=1, fontsize=label_size)\n",
    "\n",
    "ax.set_xticks(p_list)\n",
    "ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('预测模型复杂度', fontsize=label_size)\n",
    "ax.set_ylabel('房价预测误差（千美元）', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "plt.savefig('12.png', dpi=300) # Make figure clearer\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d9f351e-d064-4a5e-a201-49e0ec372daf",
   "metadata": {},
   "outputs": [],
   "source": [
    "lambda_list = [0, 1, 10, 100, 1000, 10000, 100000]\n",
    "\n",
    "b_list = []\n",
    "w_list = []\n",
    "err_list = []\n",
    "loss_list = []\n",
    "\n",
    "for lbd in lambda_list:\n",
    "    # Train model\n",
    "    w, b, logs = train_poly_mdl(x_tr1, y_tr1, x_te1, y_te1, lr=1, max_epoch=100000, batch_size=10, disp=True, regulization_method='L2', regulization_lambda=lbd)\n",
    "    b_list.append(b)\n",
    "    w_list.append(w)\n",
    "    \n",
    "    err_train = logs['err_train'][-1]\n",
    "    err_test = logs['err_test'][-1]\n",
    "    err_list.append([err_train, err_test])\n",
    "    \n",
    "    loss_train = logs['loss_train'][-1]\n",
    "    loss_test = logs['loss_test'][-1]\n",
    "    loss_list.append([loss_train, loss_test])\n",
    "\n",
    "    print(f'Lambda={lbd}\\t Training avg_err: {err_train}\\t Testing avg_err: {err_test}')\n",
    "\n",
    "b_array = np.array(b_list)\n",
    "w_array = np.array(w_list)\n",
    "err_array = np.array(err_list)\n",
    "loss_array = np.array(loss_list)\n",
    "\n",
    "# Draw errors vs lambda\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "plt.plot(xticks, err_array[:, 0], color='blue', marker='.', markersize=10, linewidth=2, zorder=1, label='Train') # Plot training losses\n",
    "plt.plot(xticks, err_array[:, 1], color='red', marker='.', markersize=10, linewidth=2, zorder=1, label='Test') # Plot training losses\n",
    "plt.legend(ncol=1, fontsize=label_size)\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Prediction Error', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "# plt.savefig('lambda_2_vs_error.png', dpi=300) # Make figure clearer\n",
    "plt.show()\n",
    "\n",
    "# Draw weights changes\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "colormap = plt.cm.get_cmap('jet', 12)\n",
    "linestyles = ['-', '--', '-.', ':', '-', '--', '-.', ':', '-', '--', '-.', ':']\n",
    "markers = ['o', 's', '^', 'v', '*', 'x', '+', 'D', 'h', 'p', '<', '>']\n",
    "for i in range(w_array.shape[1]):\n",
    "    plt.plot(xticks, w_array[:, i], color=colormap(i), linestyle=linestyles[i], marker=markers[i], markersize=7, linewidth=2, zorder=1, label=f'w{i+1}') # Plot training losses\n",
    "plt.legend(ncol=4, fontsize=label_size, loc='upper right')\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Weight Value', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "# plt.savefig('lambda_2_vs_weights.png', dpi=300) # Make figure clearer\n",
    "plt.show()\n",
    "\n",
    "b_array = np.array(b_list)\n",
    "w_array = np.array(w_list)\n",
    "err_array = np.array(err_list)\n",
    "loss_array = np.array(loss_list)\n",
    "\n",
    "# Draw errors vs lambda\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "plt.plot(xticks, err_array[:, 0], color='blue', marker='.', markersize=10, linewidth=2, zorder=1, label='Train') # Plot training losses\n",
    "plt.plot(xticks, err_array[:, 1], color='red', marker='.', markersize=10, linewidth=2, zorder=1, label='Test') # Plot training losses\n",
    "plt.legend(ncol=1, fontsize=label_size)\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Prediction Error', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "# plt.savefig('lambda_2_vs_error.png', dpi=300) # Make figure clearer\n",
    "plt.show()\n",
    "\n",
    "# Draw weights changes\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "colormap = plt.cm.get_cmap('jet', 12)\n",
    "linestyles = ['-', '--', '-.', ':', '-', '--', '-.', ':', '-', '--', '-.', ':']\n",
    "markers = ['o', 's', '^', 'v', '*', 'x', '+', 'D', 'h', 'p', '<', '>']\n",
    "for i in range(w_array.shape[1]):\n",
    "    plt.plot(xticks, w_array[:, i], color=colormap(i), linestyle=linestyles[i], marker=markers[i], markersize=7, linewidth=2, zorder=1, label=f'w{i+1}') # Plot training losses\n",
    "plt.legend(ncol=4, fontsize=label_size, loc='upper right')\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Weight Value', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "plt.savefig('16.png', dpi=300) # Make figure clearer\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9572e00b-7564-43a3-8c7a-02cd4bd20b4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "lambda_list = [0, 1, 10, 100, 1000, 10000, 100000]\n",
    "\n",
    "b_list = []\n",
    "w_list = []\n",
    "err_list = []\n",
    "loss_list = []\n",
    "\n",
    "for lbd in lambda_list:\n",
    "    # Train model\n",
    "    w, b, logs = train_poly_mdl(x_tr1, y_tr1, x_te1, y_te1, lr=1, max_epoch=100000, batch_size=10, disp=True, regulization_method='L1', regulization_lambda=lbd)\n",
    "    b_list.append(b)\n",
    "    w_list.append(w)\n",
    "    \n",
    "    err_train = logs['err_train'][-1]\n",
    "    err_test = logs['err_test'][-1]\n",
    "    err_list.append([err_train, err_test])\n",
    "    \n",
    "    loss_train = logs['loss_train'][-1]\n",
    "    loss_test = logs['loss_test'][-1]\n",
    "    loss_list.append([loss_train, loss_test])\n",
    "\n",
    "    print(f'Lambda={lbd}\\t Training avg_err: {err_train}\\t Testing avg_err: {err_test}')\n",
    "\n",
    "b_array = np.array(b_list)\n",
    "w_array = np.array(w_list)\n",
    "err_array = np.array(err_list)\n",
    "loss_array = np.array(loss_list)\n",
    "\n",
    "# Draw errors vs lambda\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "plt.plot(xticks, err_array[:, 0], color='blue', marker='.', markersize=10, linewidth=2, zorder=1, label='Train') # Plot training losses\n",
    "plt.plot(xticks, err_array[:, 1], color='red', marker='.', markersize=10, linewidth=2, zorder=1, label='Test') # Plot training losses\n",
    "plt.legend(ncol=1, fontsize=label_size)\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Prediction Error', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "# plt.savefig('lambda_1_vs_error.png', dpi=300) # Make figure clearer\n",
    "plt.show()\n",
    "\n",
    "# Draw weights changes\n",
    "fig, ax = plt.subplots(figsize=(10,6))\n",
    "\n",
    "xticks = np.arange(len(lambda_list))\n",
    "xticklabels = lambda_list\n",
    "\n",
    "colormap = plt.cm.get_cmap('jet', 12)\n",
    "linestyles = ['-', '--', '-.', ':', '-', '--', '-.', ':', '-', '--', '-.', ':']\n",
    "markers = ['o', 's', '^', 'v', '*', 'x', '+', 'D', 'h', 'p', '<', '>']\n",
    "for i in range(w_array.shape[1]):\n",
    "    plt.plot(xticks, w_array[:, i], color=colormap(i), linestyle=linestyles[i], marker=markers[i], markersize=7, linewidth=2, zorder=1, label=f'w{i+1}') # Plot training losses\n",
    "plt.legend(ncol=4, fontsize=label_size, loc='upper right')\n",
    "\n",
    "ax.set_xticks(xticks)\n",
    "ax.set_xticklabels(xticklabels)\n",
    "# ax.set_ylim(0, 25)\n",
    "\n",
    "ax.set_xlabel('Lambda', fontsize=label_size)\n",
    "ax.set_ylabel('Weight Value', fontsize=label_size)\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "plt.savefig('17', dpi=300) # Make figure clearer\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cad23b20-9942-43ac-ba4a-ed1bb6bfe884",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set cross validation methods\n",
    "cv_methods = ['leave-p-out', 'k-fold', 'boostrapping']\n",
    "\n",
    "# Split data into train and test sets\n",
    "X_tr2, x_te2, Y_tr2, y_te2 = train_test_split(data, target, test_size=0.2)\n",
    "print(f'Training dataset size: {X_tr2.shape[0]}, testing dataset size: {x_te2.shape[0]}')\n",
    "\n",
    "# Leave-p-out: Split X_tr2 and Y_tr2 into train and cross-validation sets with train-val ratio\n",
    "tr_val_ratio = 0.1\n",
    "x_tr2, x_val2, y_tr2, y_val2 = train_test_split(X_tr2, Y_tr2, test_size=tr_val_ratio)\n",
    "print(f'Training dataset size: {x_tr2.shape[0]}, cross-validation dataset size: {x_val2.shape[0]}')\n",
    "\n",
    "# Leave-p-out: Select p random samples as cross-validation data\n",
    "random_indices = np.random.permutation(X_tr2.shape[0])\n",
    "val_num = 10 # Set the number of test data\n",
    "train_idx = random_indices[val_num:]\n",
    "val_idx = random_indices[:val_num]\n",
    "x_tr2 = X_tr2[train_idx, :]\n",
    "y_tr2 = Y_tr2[train_idx]\n",
    "x_te2 = X_tr2[val_idx, :]\n",
    "y_te2 = Y_tr2[val_idx]\n",
    "print(f'Training dataset size: {x_tr2.shape[0]}, cross-validation dataset size: {x_te2.shape[0]}')\n",
    "\n",
    "# K-fold: Divide training dataset into K folds and leave one fold for CV in each time\n",
    "from sklearn.model_selection import KFold\n",
    "k = 5\n",
    "kf = KFold(n_splits=k)\n",
    "\n",
    "# Display kfold number and datasets size\n",
    "for ifold, (train_index, val_index) in enumerate(kf.split(X_tr2)):\n",
    "    x_tr2, x_te2 = X_tr2[train_index], X_tr2[val_index]\n",
    "    y_tr2, y_te2 = Y_tr2[train_index], Y_tr2[val_index]\n",
    "    print(f'Train-CV samples in fold {ifold+1}: {x_tr2.shape[0]}-{x_te2.shape[0]}')\n",
    "\n",
    "# K-fold: Manual\n",
    "k = 5\n",
    "fold_size = X_tr2.shape[0] // k # Calculate the size of each fold\n",
    "fold_indices = np.array_split(random_indices, k) # Split the indices into k folds\n",
    "for ifold in range(k):\n",
    "    val_idx = fold_indices[ifold]\n",
    "    train_idx = np.concatenate([fold_indices[i] for i in range(k) if i != ifold])\n",
    "\n",
    "    x_tr2 = X_tr2[train_idx, :]\n",
    "    y_tr2 = Y_tr2[train_idx]\n",
    "    x_te2 = X_tr2[val_idx, :]\n",
    "    y_te2 = Y_tr2[val_idx]\n",
    "\n",
    "    print(f'Train-CV samples in fold {ifold+1}: {x_tr2.shape[0]}-{x_te2.shape[0]}')\n",
    "\n",
    "# Boostrapping\n",
    "bt_set_num = 10\n",
    "\n",
    "# Generate 10 random number bigger than 10\n",
    "train_size_list = [np.random.randint(200, 500) for _ in range(bt_set_num)]\n",
    "print(f'Boostrapping training data sets: {train_size_list}')\n",
    "val_size_list = [np.random.randint(50, 100) for _ in range(bt_set_num)]\n",
    "print(f'Boostrapping cross-validation data sets: {val_size_list}')\n",
    "\n",
    "train_sample_dict = {}\n",
    "val_sample_dict = {}\n",
    "for ibt in range(bt_set_num):\n",
    "    \n",
    "    # Get indices of training and testing data\n",
    "    train_sample_dict[ibt] = np.random.choice(X_tr2.shape[0], train_size_list[ibt], replace=True)\n",
    "    val_sample_dict[ibt] = np.random.choice(X_tr2.shape[0], val_size_list[ibt], replace=True)\n",
    "\n",
    "for ibt in range(bt_set_num):\n",
    "    print(f'Training dataset size: {train_sample_dict[ibt].shape[0]}, cross-validation dataset size: {val_sample_dict[ibt].shape[0]}')  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db2db97c-02f4-4c3d-ac86-3f8b70ffa289",
   "metadata": {},
   "source": [
    "# 实验四"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23f96156-be14-4833-9b0c-01adc61e8775",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "from sklearn import svm\n",
    "from sklearn import tree\n",
    "from sklearn.linear_model import LogisticRegression, LinearRegression\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, mean_absolute_error\n",
    "from sklearn.metrics import classification_report, confusion_matrix\n",
    "import seaborn as sns\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.multiclass import OneVsRestClassifier\n",
    "from sklearn.multiclass import OneVsOneClassifier\n",
    "from sklearn.metrics import roc_curve, auc\n",
    "\n",
    "import time\n",
    "\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "color_list = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan']\n",
    "\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "# Load the MNIST dataset to display\n",
    "imgDisp = torchvision.datasets.MNIST(root='./data', train=False, download=True)\n",
    "img, label = imgDisp[0]\n",
    "\n",
    "print(f'Image size is {img.size}')\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,7))\n",
    "ax.imshow(img, cmap='gray') # Display image\n",
    "ax.tick_params(axis='both', which='major', labelsize=ticklabel_size) # Set tick label size\n",
    "ax.set_title(f\"Label: {label}\", fontsize=label_size)\n",
    "plt.savefig('1.png', dpi=300) # Make figure clearer\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d7e26aa-b66e-4cbc-97a1-2bfd2c7a0a05",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ftrExtract(object):\n",
    "    '''\n",
    "    This class is used to extract features of images\n",
    "    '''\n",
    "    def __call__(self, tensor):\n",
    "        tensor = tensor.squeeze() # Compress redundant demensions\n",
    "\n",
    "        mean_width = tensor.mean(axis=0)\n",
    "        mean_height = tensor.mean(axis=1)\n",
    "\n",
    "        std_width = tensor.std(axis=0)\n",
    "        std_height = tensor.std(axis=1)\n",
    "\n",
    "        ftrs = torch.cat([mean_width, mean_height, std_width, std_height])\n",
    "\n",
    "        return ftrs\n",
    "\n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([transforms.ToTensor(), ftrExtract()])\n",
    "\n",
    "# Load the MNIST dataset\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=True, transform=transform)\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=True, transform=transform)\n",
    "\n",
    "# Count number of each class in trainset\n",
    "train_class_counts = {}\n",
    "for _, label in trainset:\n",
    "    if label not in train_class_counts:\n",
    "        train_class_counts[label] = 0\n",
    "    train_class_counts[label] += 1\n",
    "\n",
    "# Count number of each class in testset\n",
    "test_class_counts = {}\n",
    "for _, label in testset:\n",
    "    if label not in test_class_counts:\n",
    "        test_class_counts[label] = 0\n",
    "    test_class_counts[label] += 1\n",
    "\n",
    "# Print results\n",
    "for i in range(10):\n",
    "    cls_counts_train = train_class_counts.get(i, 0)\n",
    "    cls_ratio_train = cls_counts_train / len(trainset)\n",
    "    cls_counts_test = test_class_counts.get(i, 0)\n",
    "    cls_ratio_test = cls_counts_test / len(testset)\n",
    "\n",
    "    print(f\"Class {i}: Trainset - {cls_counts_train} ({cls_ratio_train:.2%}), Testset - {cls_counts_test} ({cls_ratio_test:.2%})\")\n",
    "\n",
    "batch_size = 42\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=0)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trainloader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "input_size = data[0].numpy().shape[0]\n",
    "print(f'Input_size is {input_size}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e023d380-8723-4d95-be3d-ff83414b741e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Extract features and labels from trainset\n",
    "x_train = []\n",
    "y_train = []\n",
    "for image, label in trainset:\n",
    "    x_train.append(image.numpy())\n",
    "    y_train.append(1 if label == 1 else 0)  # Set label to 1 for character 1, 0 otherwise\n",
    "\n",
    "x_train = np.array(x_train)\n",
    "y_train = np.array(y_train)\n",
    "\n",
    "# Extract features and labels from trainset\n",
    "x_test = []\n",
    "y_test = []\n",
    "for image, label in testset:\n",
    "    x_test.append(image.numpy())\n",
    "    y_test.append(1 if label == 1 else 0)  # Set label to 1 for character 1, 0 otherwise\n",
    "\n",
    "x_test = np.array(x_test)\n",
    "y_test = np.array(y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "122ab63c-9cbc-4911-92e8-b2989c020dff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define linear function\n",
    "def linear(X, w, b):\n",
    "    '''        \n",
    "    Parameters:\n",
    "    X (numpy array): Input features, shape (n_samples, n_features)\n",
    "    w (numpy array): Weight vector, shape (n_features,)\n",
    "    b (float): Bias term\n",
    "    '''\n",
    "    return np.dot(X, w) + b\n",
    "\n",
    "# Define sigmoid function\n",
    "def sigmoid(z):\n",
    "    return 1 / (1 + np.exp(-z))\n",
    "\n",
    "# Define forward function\n",
    "def forward(X, w, b):\n",
    "    '''        \n",
    "    Parameters:\n",
    "    X (numpy array): Input features, shape (n_samples, n_features)\n",
    "    w (numpy array): Weight vector, shape (n_features,)\n",
    "    b (float): Bias term\n",
    "    '''\n",
    "    return sigmoid(linear(X, w, b))\n",
    "\n",
    "# Predict probability function\n",
    "def predict(X, w, b):\n",
    "    y_proba = forward(X, w, b)\n",
    "    y_pred = (y_proba >= 0.5).astype(int)\n",
    "    return y_pred, y_proba\n",
    "\n",
    "# Binary cross-entropy\n",
    "def binary_cross_entropy(y, y_pred, eps=1e-15):\n",
    "    return -(y * np.log(y_pred + eps) + (1 - y) * np.log(1 - y_pred + eps))\n",
    "    \n",
    "# Define compute_loss function\n",
    "def compute_loss(X, y, w, b):\n",
    "    \"\"\"\n",
    "    Compute the binary cross-entropy loss for logistic regression.\n",
    "    \n",
    "    Parameters:\n",
    "    X (numpy array): Input features, shape (n_samples, n_features)\n",
    "    y (numpy array): True labels, shape (n_samples,)\n",
    "    w (numpy array): Weight vector, shape (n_features,)\n",
    "    b (float): Bias term\n",
    "    \n",
    "    Returns:\n",
    "    float: Average binary cross-entropy loss\n",
    "    \"\"\"    \n",
    "    n = X.shape[0] # number of samples\n",
    "    \n",
    "    # Compute model predictions\n",
    "    y_pred = forward(X, w, b)\n",
    "    \n",
    "    # Compute loss\n",
    "    loss = 1/n * np.sum(binary_cross_entropy(y, y_pred))\n",
    "    \n",
    "    return loss\n",
    "\n",
    "# Compute gradients\n",
    "def compute_gradients(X, y, w, b):\n",
    "    \"\"\"\n",
    "    Compute the gradients for logistic regression.\n",
    "    \n",
    "    Parameters:\n",
    "    X (numpy array): Input features, shape (n_samples, n_features)\n",
    "    y (numpy array): True labels, shape (n_samples,)\n",
    "    w (numpy array): Weight vector, shape (n_features,)\n",
    "    b (float): Bias term\n",
    "    \n",
    "    Returns:\n",
    "    dw: gradients of weights\n",
    "    db: gradients of bias\n",
    "    \"\"\"\n",
    "    n = X.shape[0] # number of samples\n",
    "    \n",
    "    # Compute model predictions\n",
    "    y_pred = forward(X, w, b)\n",
    "    \n",
    "    dw = 1/n * np.dot(X.T, (y_pred - y))\n",
    "    db = 1/n * np.sum(y_pred - y)\n",
    "    \n",
    "    return dw, db\n",
    "\n",
    "# Train logistic regression model\n",
    "def train_logistic_regression(X, y, learning_rate=0.01, num_iterations=1000):\n",
    "    \"\"\"\n",
    "    Compute the gradients for logistic regression.\n",
    "    \n",
    "    Parameters:\n",
    "    X (numpy array): Input features, shape (n_samples, n_features)\n",
    "    y (numpy array): True labels, shape (n_samples,)\n",
    "    \n",
    "    Returns:\n",
    "    w: weights of logistic regression model\n",
    "    b: bias of logistic regression model\n",
    "    \"\"\"\n",
    "    eps = 1e-15\n",
    "    _, ftr_num = X.shape\n",
    "    \n",
    "    w = np.zeros(ftr_num)\n",
    "    b = 0.0\n",
    "    \n",
    "    # Initialize Adagrad accumulators\n",
    "    lr_w = np.zeros(ftr_num)\n",
    "    lr_b = 0.0\n",
    "    \n",
    "    for i in range(num_iterations):\n",
    "        # Compute loss and gradients\n",
    "        loss = compute_loss(X, y, w, b)\n",
    "        dw, db = compute_gradients(X, y, w, b)\n",
    "        \n",
    "        # Update accumulators\n",
    "        lr_w = dw ** 2\n",
    "        lr_b = db ** 2\n",
    "        \n",
    "        # Update parameters\n",
    "        w -= learning_rate / (np.sqrt(lr_w) + eps) * dw\n",
    "        b -= learning_rate / (np.sqrt(lr_b) + eps) * db\n",
    "        \n",
    "        # Print loss every 100 iterations\n",
    "        if i % 100 == 0:\n",
    "            print(f\"Iteration {i}, Loss: {loss}\")\n",
    "    \n",
    "    return w, b\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf163206-4f96-43c7-a623-fd424325d8eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Generate prediction values\n",
    "y_pred = np.linspace(0.001, 0.999, 1000)\n",
    "\n",
    "# Compute loss for y_true = 1 and y_true = 0\n",
    "loss_y1 = binary_cross_entropy(1, y_pred)\n",
    "loss_y0 = binary_cross_entropy(0, y_pred)\n",
    "\n",
    "# Plotting\n",
    "fig, ax_y1 = plt.subplots(figsize=(10, 6))\n",
    "ax_y1.plot(y_pred, loss_y1, label='y_true = 1', color='blue')\n",
    "ax_y1.set_xlabel('Predicted y', fontsize=label_size)\n",
    "ax_y1.set_ylabel('Loss', fontsize=label_size)\n",
    "ax_y1.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "plt.tight_layout()\n",
    "plt.savefig('binary_cross_entropy_loss1.png', dpi=300)\n",
    "plt.show()\n",
    "\n",
    "# Plotting\n",
    "fig, ax_y0 = plt.subplots(figsize=(10, 6))\n",
    "plt.plot(y_pred, loss_y0, label='y_true = 0', color='red')\n",
    "ax_y0.set_xlabel('Predicted y', fontsize=label_size)\n",
    "ax_y0.set_ylabel('Loss', fontsize=label_size)\n",
    "ax_y0.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "plt.tight_layout()\n",
    "plt.savefig('7.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da8d0a06-1e99-4357-8e6f-fd95ca55a063",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Generate x values\n",
    "x = np.linspace(0.01, 5, 1000)\n",
    "\n",
    "# Compute natural logarithm\n",
    "y = -np.log(x)\n",
    "\n",
    "# Create the plot\n",
    "fig, ax_log = plt.subplots(figsize=(6, 6))\n",
    "\n",
    "ax_log.plot(x, y, label='ln(x)', color='k', linewidth=2)\n",
    "\n",
    "ax_log.set_xlabel('x', fontsize=label_size)\n",
    "ax_log.set_ylabel('log$_e$(x)', fontsize=label_size)\n",
    "ax_log.tick_params(axis='both', which='major', labelsize=ticklabel_size)\n",
    "\n",
    "ax_log.set_xlim(-0.05, 5)\n",
    "ax_log.set_ylim(-2, 4)\n",
    "# Add vertical line at x=1\n",
    "ax_log.axvline(x=1, color='gray', linestyle='--')\n",
    "\n",
    "# Add horizontal line at y=0\n",
    "ax_log.axhline(y=0, color='gray', linestyle='--')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.savefig('8.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d6bba295-c0bf-4af6-8a3e-d56ff745492c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Train the model\n",
    "w, b = train_logistic_regression(x_train, y_train)\n",
    "\n",
    "y_pred, y_proba = predict(x_test, w, b)\n",
    "\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "precision = precision_score(y_test, y_pred)\n",
    "recall = recall_score(y_test, y_pred)\n",
    "f1 = f1_score(y_test, y_pred)\n",
    "\n",
    "print(f'Precision: {precision:.4f}, Recall: {recall:.4f}, Accuracy: {accuracy:.4f}, F1-Score: {f1:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4fb3c87-8cbd-4111-97f9-ec75c2bc1423",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Random select 3 examples from imgDisp and testset\n",
    "np.random.seed(42)\n",
    "idx = np.random.choice(len(imgDisp), 3)\n",
    "\n",
    "# Select instances\n",
    "imgDisp_select = [imgDisp[i] for i in idx]\n",
    "x_select = x_test[idx]\n",
    "y_select = y_test[idx]\n",
    "\n",
    "y_select_pred, y_select_proba = predict(x_select, w, b)\n",
    "\n",
    "# Check the selected instances' labels are the same\n",
    "for i in range(len(idx)):\n",
    "    print(f'Sample {i+1}: imgDisp label is {imgDisp_select[i][1]}, x label is {y_select[i]}')\n",
    "\n",
    "    # Display image from imgDisp\n",
    "    fig, ax = plt.subplots(figsize=(7,7))\n",
    "    ax.imshow(imgDisp_select[i][0], cmap='gray')\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size) # Set tick label size\n",
    "    ax.set_title(f\"Label: {imgDisp_select[i][1]}, Prediction: {y_select_proba[i]:.4f}\", fontsize=label_size)\n",
    "\n",
    "    plt.savefig('9', dpi=300) # Make figure clearer\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91598bb9-2706-477f-ab65-b8c7a7a0c449",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define SVM classifier\n",
    "mdl_svm = svm.SVC(kernel='linear', probability=True)\n",
    "\n",
    "# Train model\n",
    "start_time = time.time()\n",
    "mdl_svm.fit(x_train, y_train)\n",
    "end_time = time.time()\n",
    "\n",
    "print(f'Training time: {end_time - start_time:.2f} seconds')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78e90466-971c-424d-9d9f-6da92fb294d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make predictions and evaluate the model\n",
    "y_pred_svm = mdl_svm.predict(x_test)\n",
    "y_proba_svm = mdl_svm.predict_proba(x_test) # Output ratio\n",
    "\n",
    "accuracy = accuracy_score(y_test, y_pred_svm)\n",
    "precision = precision_score(y_test, y_pred_svm)\n",
    "recall = recall_score(y_test, y_pred_svm)\n",
    "f1 = f1_score(y_test, y_pred_svm)\n",
    "\n",
    "print(f'Precision: {precision:.4f}, Recall: {recall:.4f}, Accuracy: {accuracy:.4f}, F1-Score: {f1:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b35d919f-c6da-4eb3-aa47-cd14a9d58a3f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Extract features and labels from trainset\n",
    "x_train = []\n",
    "y_train = []\n",
    "for image, label in trainset:\n",
    "    x_train.append(image.numpy())\n",
    "    y_train.append(label)\n",
    "\n",
    "x_train = np.array(x_train)\n",
    "y_train = np.array(y_train)\n",
    "\n",
    "# Extract features and labels from trainset\n",
    "x_test = []\n",
    "y_test = []\n",
    "for image, label in testset:\n",
    "    x_test.append(image.numpy())\n",
    "    y_test.append(label)\n",
    "\n",
    "x_test = np.array(x_test)\n",
    "y_test = np.array(y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9caaff32-41cc-49df-9242-7e135b78ce08",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define logic multi-classifier\n",
    "mdl_logic_ovr = OneVsRestClassifier(LogisticRegression(max_iter=1000))\n",
    "\n",
    "# Train model\n",
    "start_time = time.time()\n",
    "mdl_logic_ovr.fit(x_train, y_train)\n",
    "end_time = time.time()\n",
    "\n",
    "print(f'Training time: {end_time - start_time:.2f} seconds')\n",
    "\n",
    "# Make predictions and evaluate the model\n",
    "y_pred_logic_ovr = mdl_logic_ovr.predict(x_test)\n",
    "y_proba_logic_ovr = mdl_logic_ovr.predict_proba(x_test) # Output ratio\n",
    "\n",
    "accuracy = accuracy_score(y_test, y_pred_logic_ovr)\n",
    "print(f'Accuracy: {accuracy:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d14408c-1372-4619-8632-15acd0e95204",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get class list: 0, 1, ..., 9\n",
    "class_list = np.sort(np.unique(y_train))\n",
    "\n",
    "# Create model list\n",
    "mdl_logic_list = []\n",
    "for c in class_list:\n",
    "    mdl_logic_list.append(LogisticRegression(max_iter=1000))\n",
    "\n",
    "# Train models seperately\n",
    "for i in range(len(class_list)):\n",
    "    start_time = time.time()\n",
    "    mdl_logic_list[i].fit(x_train, (y_train == class_list[i]).astype(int))\n",
    "    end_time = time.time()\n",
    "    print(f'Training class {class_list[i]}, Training time: {end_time - start_time:.2f} seconds')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db06ee33-1382-4bef-9a04-6eaaad9f8029",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot ROC curve\n",
    "fig, ax = plot_roc_curve_base()\n",
    "\n",
    "# Draw ROC of individual classifier\n",
    "for i in range(len(class_list)):\n",
    "    # Make predictions and evaluate the model\n",
    "    y_test_trans = (y_test == class_list[i]).astype(int)\n",
    "    y_proba = mdl_logic_list[i].predict_proba(x_test) # Output ratio\n",
    "\n",
    "    roc_auc_logic, fpr_logic, tpr_logic, thresholds_logic = add_roc_curve(ax, y_test_trans, y_proba[:,1], color_list[i], f'{class_list[i]}')\n",
    "\n",
    "plt.legend(loc=\"lower right\", fontsize=ticklabel_size)\n",
    "plt.savefig('14.png', dpi=300) # Make figure clearer\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d1d6d1b-16a2-4abb-8f2d-68e23d738dd5",
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_num = 10\n",
    "\n",
    "# Random select 3 examples from imgDisp and testset\n",
    "np.random.seed(1)\n",
    "idx = np.random.choice(len(imgDisp), sample_num)\n",
    "\n",
    "# Select instances\n",
    "imgDisp_select = [imgDisp[i] for i in idx]\n",
    "testset_select = [testset[i] for i in idx]\n",
    "\n",
    "# Check the selected instances' labels are the same\n",
    "for i in range(sample_num):\n",
    "    x = testset_select[i][0].view(-1, input_size)\n",
    "\n",
    "    # Using model to predict character\n",
    "    y_pred_list = []\n",
    "    for j in range(len(mdl_logic_list)):\n",
    "        y_pred_list.append(mdl_logic_list[j].predict(x))\n",
    "\n",
    "    y_pred = np.argmax(np.array(y_pred_list), axis=0)[0]\n",
    "\n",
    "    # Display image from imgDisp\n",
    "    fig, ax = plt.subplots(figsize=(7,7))\n",
    "    ax.imshow(imgDisp_select[i][0], cmap='gray')\n",
    "    ax.tick_params(axis='both', which='major', labelsize=ticklabel_size) # Set tick label size\n",
    "    ax.set_title(f\"Label: {imgDisp_select[i][1]}, Prediction Label: {y_pred}\", fontsize=label_size)\n",
    "\n",
    "    print(f'Sample {i+1}: imgDisp label is {imgDisp_select[i][1]}, testset label is {testset_select[i][1]}, predict label is {y_pred}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "631eb601-cd29-41ec-9023-e82ebcefb900",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Prediction\n",
    "y_pred_list = []\n",
    "for i in range(len(mdl_logic_list)):\n",
    "    y_pred_list.append(mdl_logic_list[i].predict(x_test))\n",
    "\n",
    "y_pred = np.argmax(np.array(y_pred_list), axis=0)\n",
    "\n",
    "# Accuracy\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "print(f'Accuracy: {accuracy:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c67f9583-a5b7-4d93-8e3f-5dd517e9be44",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define DecisionTree classifier\n",
    "mdl_dt = tree.DecisionTreeClassifier()\n",
    "\n",
    "# Train model\n",
    "start_time = time.time()\n",
    "mdl_dt.fit(x_train, y_train)\n",
    "end_time = time.time()\n",
    "\n",
    "print(f'Training time: {end_time - start_time:.2f} seconds')\n",
    "\n",
    "# Define Random Forest classifier\n",
    "mdl_rf = RandomForestClassifier(n_estimators=100)\n",
    "\n",
    "# Train model\n",
    "start_time = time.time()\n",
    "mdl_rf.fit(x_train, y_train)\n",
    "end_time = time.time()\n",
    "\n",
    "print(f'Training time: {end_time - start_time:.2f} seconds')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6062d2d1-2ff7-4d0d-ba2a-57d90cb6e8b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred_dt = mdl_dt.predict(x_test)\n",
    "y_proba_dt = mdl_dt.predict_proba(x_test) # Output ratio\n",
    "\n",
    "accuracy = accuracy_score(y_test, y_pred_dt)\n",
    "precision = precision_score(y_test, y_pred_dt)\n",
    "recall = recall_score(y_test, y_pred_dt)\n",
    "f1 = f1_score(y_test, y_pred_dt)\n",
    "\n",
    "print(f'Precision: {precision:.4f}, Recall: {recall:.4f}, Accuracy: {accuracy:.4f}, F1-Score: {f1:.4f}')\n",
    "\n",
    "y_pred_rf = mdl_rf.predict(x_test)\n",
    "y_proba_rf = mdl_rf.predict_proba(x_test) # Output ratio\n",
    "\n",
    "accuracy = accuracy_score(y_test, y_pred_rf)\n",
    "precision = precision_score(y_test, y_pred_rf)\n",
    "recall = recall_score(y_test, y_pred_rf)\n",
    "f1 = f1_score(y_test, y_pred_rf)\n",
    "\n",
    "print(f'Precision: {precision:.4f}, Recall: {recall:.4f}, Accuracy: {accuracy:.4f}, F1-Score: {f1:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a88eb985-7455-4735-b6b0-c0a6c6d4efc6",
   "metadata": {},
   "source": [
    "# 实验五"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "68270157-458b-452a-8c3c-86eaf821fce2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix:\n",
      "[[134  22]\n",
      " [ 18 126]]\n",
      "True Negatives (TN): 134\n",
      "False Positives (FP): 22\n",
      "False Negatives (FN): 18\n",
      "True Positives (TP): 126\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhoAAAIyCAYAAACNRmN9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA81UlEQVR4nO3de5xO5f7/8fea85hhjNNgaNLBqXKOmBxC4asiFdmSancQ+mHrQCpKobSTtorSFrWlUg5l+yKH7VwUUo0kYxgychjDGHO8fn/4zr3dzdE9c809Y17Px2MeD7PWda31udcM99t1X+tajjHGCAAAwAIfbxcAAAAuXQQNAABgDUEDAABYQ9AAAADWEDQAAIA1BA0AAGANQQMAAFhD0AAAANYQNAAAgDUEDeASsGvXLvXt21e1atWSn5+fHMdRs2bNvFbP2rVr5TiOHMfxWg3I3f79+10/m/3793u7HJQDBA3g/2RmZurTTz/Vfffdp/r166ty5coKCAhQjRo1dOONN2rMmDH68ccfvV1mDrGxsYqOjtZnn32mI0eOKCwsTBEREapWrZq3SyuTst+EHcdRo0aNCmy/detWtz73339/sdazY8cOjR8/Xm+88UaxHhcoKX7eLgAoDbZs2aJBgwZpz549rm3+/v6qWLGijh8/ro0bN2rjxo2aPHmy+vTpo48//lgBAQFerPi/Zs6cqdOnT+uqq67SmjVrVKdOHW+XpAoVKqhBgwbeLqPIdu/erc2bN6tt27Z5tvnnP/9ptYYdO3bohRdeUFRUlEaMGFHk4/n7+7t+Nv7+/kU+HlAQRjRQ7n355Zfq1KmT9uzZo6pVq2rSpEnas2eP0tLSdPz4caWlpWnr1q0aPXq0KlWqpC+++EJnz571dtkuu3btkiT16tWrVIQMSWrdurV2796t3bt3e7sUj11++eWSpNmzZ+fZ5ty5c5o/f74cx9Fll11WQpUVTWRkpOtnExkZ6e1yUA4QNFCu/frrr7r33nuVmpqqxo0ba8eOHRo9erSuvvpqVxtfX1+1atVKkyZNUmxsrHr16uXFinPKDj2hoaFeruTSct9998lxHH3yySd5BssvvvhCiYmJ6tixo+rVq1fCFQJlA0ED5dqzzz6rpKQkBQUFaeHChQWOCFSpUkWLFi1SWFhYjn1HjhzRk08+qWuuuUahoaEKCQnRNddco6eeekoJCQm5Hu/PE/MSEhI0fPhw1atXT0FBQYqIiNA999yT68jA5ZdfLsdxtHbtWknSCy+84DZXIHv7+PHj5TiOOnXqlOfrKmjy5jfffKMBAwa46goJCVFUVJQ6duyoCRMmKD4+/qKO543rdbHq1aunjh07KikpSZ9//nmubbI/NnnggQfyPVZKSoqWLFmihx9+WM2aNVP16tUVGBio2rVrq3fv3lq2bFmu/RzHcR07Li7O7efrOI7Gjx/vanv//fe75ogYYzRr1izdeOONqlq1qhzH0QcffCAp78mgx48fV506deQ4ju64445c68nMzFR0dLQcx1GTJk107ty5fF83IEkyQDl15MgR4+PjYySZv/71r0U61tq1a03lypWNJCPJVKhQwYSEhLi+Dw8PN+vXr8/RLzY21tXmq6++MjVq1HD1DwwMdO2rVKmS2bFjh1vfVq1amYiICOPv728kmZCQEBMREeH62rhxozHGmHHjxhlJpmPHjnnWv2bNGte5/uyDDz4wjuO49gcGBppKlSq5vpdkZs+eXejjeet6FdaFr2nOnDlGkrnppptytIuLizOO45iKFSua5ORk07FjRyPJDBo0KEfb2bNnu12v4OBgU6FCBbdto0aNytEvIiLCda19fHzcfr4RERFmypQprraDBg0yksx9991n7rrrLlef8PBw4+Pj4/oZXXgNY2Nj3c63du1a19+J6dOn56hn7Nixrvp//PHHi7uwKLcIGii3Pv74Y7c3LU8dOHDA9abZuHFjs2HDBte+devWmQYNGhhJpkqVKiY+Pt6t74X/6IeHh5vo6GizdetWY4wx6enpZuXKlaZWrVpGkmnfvn2u589+gxs3blyu+4sSNJKTk03FihWNJHPvvfeavXv3uvadOXPGbNu2zTz55JNm6dKlhTpeabheBbkwaCQnJ5tKlSoZx3HMvn373NqNHz/eSDIPPfSQMcbkGzQWLlxoHnnkEbNmzRpz7Ngx1/bDhw+bF154wRUWFy9enKNvdkiJiorKt+7soBEaGmr8/PzMa6+9Zk6dOmWMMeb06dPm8OHDxpj8g4Yxxjz33HNGkgkKCjI//PCDa/uaNWtcIWTGjBn51gJciKCBcuvZZ591/YN76NAhj48zePBg1xvf77//nmP/wYMHXf8rHTp0qNu+C//Rb9iwoTl79myO/kuWLHG1OXjwYI79NoPGN998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atCgge655x59/vnnysrKch2rXr16rn716tVzm9eS23yHzMxMffDBB+rWrZsiIiIUEBCg6tWrq1u3bpo/f36+9WdmZmr69Olq0aKFQkJCVKVKFXXq1EkLFizI9zXbdODAAb311lvq2bOn6tevr5CQEIWGhqpx48YaMWKEDhw4UKjjpKWlafLkyWrSpIlCQkIUHh6um2++WcuWLSuw72+//abHH39cjRo1UmhoqCpUqKBGjRpd1PmBYmMA5GvcuHFGksnvr8tbb73larNx40ZjjDGxsbGubf/6179MaGiokWQqVKhgQkJCTFRUlKv/6dOnza233upqL8lUqlTJOI7j+r5t27bmxIkTOc6dlZVlHnjgAVc7x3FMeHi48fHxMZLMPffcYwYNGmQkmUGDBuXo37FjRyPJjBs3LtfXNnnyZNexJJmgoCBTsWJFt1pPnjxpjDHmjjvuMNWqVXNtr1atmomIiHB93XHHHW7HPnLkiGnTpo3bscLCwty+v/32201qamqOus6dO2e6devmaufj42MqV67sumZPP/10ga8tP9l9O3bs6FG/C1/PhdcvLCzMrF+/Pt++Y8aMMe3btzeSjJ+fn6lcubLbMfN7Pe+++67x9/d3tQ0MDDTBwcFuv1crVqzI0W/NmjUF/p4DnuA3CihAYYLGk08+6WoTExNjjHEPGqGhoaZNmzZm69atrj6//PKL68+9e/c2ksxVV11l5s2bZ5KSkowxxqSkpJjFixebK664wkgyvXv3znHuadOmuc4zbNgw88cffxhjjElMTDTjx483juO43qguNmi8/fbbbm/427dvd+07fvy4WbFihenXr585deqUa/uFrzs2NjbPa5aammquv/56I8m0aNHCLF261CQnJxtjjDlz5oyZM2eOqVGjhpFkRowYkaP/yJEjXcHqpZdectWQkJBgHnvsMbfQUpJBY+jQoWby5Mnm559/NmfPnjXGGJOenm6++eYb0717dyPJ1K5d27Uvt3OGhYWZwMBAM2PGDJOSkmKMMebAgQPmrrvucl3bxYsX5+i/cOFCI8n4+/ub0aNHm/3795usrCyTlZVldu/ebe6++25X2IiLi3PrS9CALfxGAQUoKGicOnXK1K5d20gyVapUMZmZmcYY9zfcqKgoc/r06Vz7f/XVV0aSqVmzpomPj8+1zcGDB01ISIiR5PZmn5KSYqpU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",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.8667\n",
      "Precision: 0.8514\n",
      "Recall: 0.8750\n",
      "F1-Score: 0.8630\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAr0AAAIyCAYAAADGwnLVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABhyklEQVR4nO3deVxU9f7H8fdhX5RxwQVUFDXNtMzUSr1aWWm2qNktKtPM9Je31axuLu2btlyzMr0tmlmm3hLNW7ZYlkt6S03L0nIlt0HFZUBAQDi/P2gmBgYYcISZw+v5eMzjwXzP95zzHY7Uhy+f7+drmKZpCgAAALCwoOoeAAAAAHC6EfQCAADA8gh6AQAAYHkEvQAAALA8gl4AAABYHkEvAAAALI+gFwAAAJZH0AsAAADLI+gFAACA5RH0AggILVq0kGEYmjVrlk+ud/HFF8swDD3xxBM+uR5Or7KeF88SgDcIegGLeeKJJ2QYRolXRESEmjZtqv79++s///mP2IE8cM2aNcvjMw4NDVXDhg118cUXa/LkycrMzKzuoQaUnJwczZw5U9dff71atmyp2rVrKzw8XHFxcbr00kv1zDPPaNeuXdU9TACVFFLdAwBw+jRq1Mj1tcPh0L59+7Rv3z7997//1axZs7Rw4UKFh4dX4wi916pVK0VERMhms/nkegkJCWrbtq1iY2N9cr3qEhsbq+DgYElSVlaWDh06pOXLl2v58uV6/fXXtWzZMjVv3ryaR+n/PvnkE40aNUr79u1ztYWHhysqKkoHDhxQamqqli1bpieeeEL/93//p2nTplXjaAFUBjO9gIWlpqa6XpmZmfrll190+eWXS5I+++wzPfLII9U8Qu99/fXX+u2333Tttdf65HqzZ8/Wb7/9prvvvtsn16sua9eudT3j9PR0HThwQBMmTJAk7dy5U7fccks1j9D/vfHGGxowYID27dunZs2a6fXXX9fu3bt14sQJHT16VDk5OVqxYoXuuusuhYSE6IMPPqjuIQOoBIJeoIYICgpS+/bttXjxYrVu3VpS4f/sT548Wc0jgy81bNhQzzzzjIYPHy5JWrVqlbZu3VrNo/Jf3333ne6++24VFBSoV69e2rRpk+688041a9bM1Sc0NFQ9e/bU1KlTtXXrVv3tb3+rxhEDqCyCXqCGiYiI0PXXXy9JysjI0G+//SZJSklJceWGpqSkaMeOHfq///s/JSYmKjw8XC1atChxrUWLFmngwIGKj49XWFiY6tatq169eunf//638vLyyhzHnj179M9//lPnnnuubDabIiMj1apVKw0YMECzZ8/WiRMn3PqXtZAtOztbL730krp166a6desqNDRUDRo00FlnnaVbb71VCxYsKHGON4ufkpOTdfXVV6tRo0YKCwtTo0aNdPXVV2vhwoWlnjNs2DAZhqFhw4ZJkj766CNdfPHFqlevnqKionTuuefqlVdeUUFBQZnfn1N1xRVXuL7+9ddfPfbJz8/XrFmz1LdvX9dnbNCggfr27at58+aVm/e9ZcsW3XXXXTrrrLNUu3Zt1apVS23bttWNN96oBQsWlPiMv//+u1588UVddtllatWqlSIjIxUTE6NOnTrpkUceUVpa2ql/8Ap64IEHdPLkSTVs2FALFiwoN30mISFBixcvdmsr/sw9ceZhe/o5Knq+aZp6++239be//U3169d3/Zu/9957ZRiGzjvvvDLHd/z4cUVHR8swDL3//vsljp84cUKvvvqqLrroIsXGxiosLEyNGzfWwIED9fnnn5d5bSDgmQAs5fHHHzclmWX9eL/++uuuPt99951pmqa5a9cuV9ucOXPMWrVqmZLMqKgoMzo62mzevLnr/IyMDPPqq6929ZdkxsTEmIZhuN5369bNPHLkiMf7z54924yIiHD1DQsLM202m9v1NmzY4HZO8+bNTUnmO++849aenp5uduzY0XWeYRhmnTp1zJCQEFdb0bE7XXTRRaYk8/HHHy9xLCcnx0xKSnKdHxQUZNatW9cMCgpytd10001mbm5uiXNvvfVWU5J56623mnfddZfr/Dp16rh9vqFDh5b6fMrzzjvvuK6za9cuj33mz5/v6vPhhx+WOJ6ammpecMEFbmMq/gz69+9v5uTkeLz+pEmT3L4fERERZu3atd3OP3r0qNs5zmdY9DkV/TfTpEkT87fffvN4v7KeV1nHyvLDDz+47v30009X6Nyiij7z0jifmad/i87zhw4dav79738v8W/unXfeMdeuXesa6y+//FLqfWbNmmVKMmvVqmUeP37c7djWrVvNM844w+0ZFH/m//jHPyr7bQD8HjO9QA2UkpLi+rpevXoljt9xxx1q37691q5dq8zMTB0/flxffvml6/iQIUP0ySefqHXr1vrggw+Unp4uh8OhrKwsffzxx2rZsqXWrFnj+hN7UUuWLNGtt96qEydOqEePHlq5cqWys7N17NgxORwOrVixQiNHjlRYWJhXn+WVV17RTz/9pHr16mnBggXKzs525WHu27dPs2fPVp8+fSr0/Rk/frzmz58vwzD06KOP6vDhwzpy5IjS0tI0fvx4SdLcuXP16KOPlnqNxYsX66233tLkyZN19OhRHT16VGlpaRoxYoSkwpziZcuWVWhcFVF01q5ly5Zux3Jzc3XNNdfo+++/13nnnadPP/1UmZmZOnbsmI4fP653331XDRs21OLFi/Xwww+XuPb06dM1duxYFRQUqH///tqwYYOys7OVnp6uw4cP68svv1RSUpKCgtz/F3PhhRfqtdde0/bt2135sidOnNBXX32l888/X/v27dPNN998er4hHnz99deur32VK34qkpOTtWjRIr300ks6evSojhw5IofDob59+6pLly4666yzJEnvvfdeqddwHhs0aJCio6Nd7ceOHVOfPn20bds29e7dWytWrHD93B07dkyTJ09WrVq1NH36dL3yyiun94MC1aW6o24AvlXeTK/D4TDj4+NNSWa9evXM/Px80zTdZ3qbN29uZmRkeDz/k08+MSWZjRs3Nvfu3euxz549e8zo6OgSM7Z5eXlmYmKiKcn829/+VuosoielzfT269fPlGQ+99xzXl/LNEufHdy7d69rlnjcuHEezx0zZowpyQwNDTX379/vdsw5a+dprE6dO3c2JZkjRoyo0JidyprpPXjwoPnII4+4jnfs2LHE+VOnTjUlme3btzfT09M93mPdunWmYRhmWFiYeeDAAVf7kSNHXDO6N954o1lQUFCpz1BcRkaG2ahRI1OSuXLlyhLHT8dM7y233GJKMsPDw10/B5Xhq5leSearr75a6jUmTpxoSjKbNm3qcbx79+51zb5/9dVXbscefPBBU5LZu3dvMy8vz+P1k5OTTUlmbGxsqX2AQMZML1BDHDt2TF9//bV69+6t/fv3S5Luu+++ErNxknT33XerVq1aHq/z9ttvSyqc7W3SpInHPk2bNtUll1wiSfriiy9c7d98842rzunLL7/s9WxuWerUqSNJstvtp3wtSVqwYIFOnjypiIgIjR071mOfRx55ROHh4crLy9NHH33ksU+zZs00dOhQj8f69+8vSfr5559Pebxdu3ZV48aN1bhxY8XExLgWsklS48aNNWfOnBLnOJ/hnXfeqdq1a3u8bufOndW+fXvl5ubqm2++cbV/9NFHysjIUGhoqCZPnizDME75M0hSrVq1dNFFF0kqXHxXFQ4fPiyp8N+Qp5+Dqla3bl3dcccdpR6/5ZZbFBQUpL1797o9E6c5c+aooKDA7edPkkzT1MyZMyUV5jCHhHiuVjpw4EDFxMQoLS1N69evP8VPA/gf6vQCFlZWQHLLLbe4SlsV16NHj1LPcwYkb775pmbPnl1qP4fDIUn6448/XG2rV6+WVBiMdenSpfSBV8DVV1+tuXPnaurUqTp06JCSkpL0t7/9rdL1d9etWyepMJiMiYnx2Kdu3brq0qWLvvvuO1f/4rp27VpqIBUfHy9JOnLkSKXGWFRpi78uv/xyffTRRyU+Q0ZGhivYfvTRR/XUU0+Vem3n+Dw9w86dOysuLq7C4/3kk0/03nvvae3atTpw4ICysrJK9Nm7d2+Fr1sZ5p8L9XwVuJ+qrl27lvmLYNOmTXXxxRdr2bJleu+993TppZe6HXemNgwePNjt397mzZtdz3LYsGFlBvjHjx+XVPjML7jggkp/FsAfEfQCFlZ0c4rw8HDFxsaqU6dOGjx4sNtMUHENGzb02J6Xl+cKshwOhyuwLUvRoCY1NVWSfLpZws0336wffvhBr732mubNm6d58+ZJklq3bq0+ffpo+PDh6ty5s9fXO3jwoCSVOovt1LRpU7f+xZU2gyrJNdNWvMLFoEGDXEFlUc2aNdPatWs9XmvXrl2uigAHDx7U119/rX/+859aunSpxo8fr6lTp7r1T01NdVVV8Dbo9sUzLCgo0C233KK5c+e62kJCQlS3bl1XoOdwOHTixIkq20nO+YvR0aNHVVBQUO2zvaX93BU1dOhQLVu2TAsWLNC0adMUFRUlSdq4caN++eUXV5+inH/ZkaRDhw55NRZPv4wAgY6gF7AwZ4BSUc4dvorLz893fT1v3jwlJSVV6vq+nlmbMmWK7r77bn344YdauXKl1qxZo+3bt2v79u2aNm2a7rvvPk2ZMuW0jNGXn+XIkSM6cOBAifaIiAivzm/YsKFuuukmderUSeedd55ef/11denSxa2UVtFn+L///a/Ss3kV/dwzZszQ3LlzFRwcrAkTJmjIkCFq2bKlW6A5ZMgQvf/++1W2RXb79u0lFW4/vGXLFtf76lLaz11R1113ne68804dP35cCxcu1ODBgyX9NcvbuXNn14I3p6LPPDU11e2XYaAmqf4kJgABo+g2wJs2barw+c4/hzvzen2pdevWGjdunJYsWaLDhw9rzZo1GjhwoKTCCg/Fa6uWxjnbtmfPnjL7Of8E36BBg8oPuphvv/1WpmmWeBWttuGNM888Uw899JAk6aGHHlJ6errrWNGA51SeYUXH5JyBHzFihJ588km1bt26xMxqZX9Jq6yi6QFl1V4uj3Pmvnht6aK8+auIN2rVquWqNOEMdPPz810z6EOGDClxTuPGjV1fV+aZA1ZB0AugQpz5vh9++GGFN1jo3r27JOnAgQOl5sL6QlBQkC688EJ99NFHSkhIkCQtXbrUq3Oducbr1q0rNVA5duyYW+6vPxozZoxsNpvS0tL00ksvudrr1q3rmgl0BqIV4XyG69atq9DiQecvEZ06dfJ4/Pjx4/r+++8rPJ5T0bVrV51//vmSpKlTp3q9OUbxf/d169aVVPYvSr78bM70ha+++kqpqan66quvZLfbFRISoptuuqlE/w4dOrhyuyvzzAGrIOgFUCH/93//J0naunWrXnzxxTL7ZmZmKjc31/X+kksucdWMvf/++92OVVZOTk6px4KDg135ot786Vgq/PNxSEiITpw4oeeff95jn+eee045OTkKDQ3VddddV/FBVwGbzaa77rpLUmH6h7NSgfTXM/z666/LDYKK5/1ef/31iomJ0cmTJ3X//fd7nYrg/AvBTz/95PH4008/rYyMDK+u5UsvvfSSgoODdeDAAV133XXlzsju3bvX9RcEp44dO0qS1q5d6zHw3bJli5KTk3025ssuu0zx8fHKz8/XnDlzXDO+V1xxhce84JCQEFfN7Hfffbfc6hi+WGAJ+COCXgAVMmDAANefV8eOHat//OMf2rp1q+t4bm6uvv/+ez388MNq3ry520Kv4OBgTZ06VYZhaNWqVbr00ku1atUq18xZenq6vv32W91yyy3avHmzV+O54IILdO+99+rbb791WwC1f/9+3XPPPdq+fbsk6corr/Tqek2aNNF9990nSZo0aZIef/xxHTt2TFLhDO+jjz7qCvbHjBlTqQoGVWX06NGKiopSRkaG2y8oo0aNcuXyDhkyRI888ohbsJaVlaVvv/1Wd999t1q1auV2TZvNphdeeEGSNH/+fF177bXauHGj6/jRo0f16aefasCAAW5pFc5tkd966y29+eabrl94UlNTdf/99+uFF15Q/fr1ffsN8ELPnj31yiuvyDAMrVixQuecc46mT5/uVkEiLy9Pq1ev1ujRo9WmTRutWLHC7RrXXHONatWqpby8PN1www36/fffXed9/PHHuuyyy9w2ijhVQUFBrk08ZsyYoUWLFknynNrg9Oijj6pVq1Y6efKkrrjiCk2ePNltUZvD4dDnn3+uW2+9VT179vTZWAG/Um0VggGcFt5sQ+xJ0c0pStva1ikzM9O88cYb3bYvjY6OLrFVrySPG1i8++67Znh4uKtPeHh4iW16vd2G2NPWts6NMZyv+++/v8QYytuG+IYbbjjlbYhLU9ZGBd7wZhtip/vuu8/1fIpuMnHo0CGzd+/ebt+nmJiYElsDh4SEeLzuc8895/b9iIyMLHMb4qNHj5pnnnmm2/e06L3uuOOOMr93p2NziqIWLVpkxsXFuY0/IiLCrFu3bonvx+jRo0uc//bbb7udW7t2bTMsLMyUZF544YWuDUHK2pyirH8zxW3atMntfjabzczOzi7znJ07d7pt2S3JrFOnjhkTE+PW1rp1a6/HAQQSZnoBVFhUVJTmzp2rb775xrUKv6CgQMePH1fDhg3Vu3dvvfDCC9q2bZvH0l9Dhw7Vb7/9ptGjR+uss85SSEiIcnNz1apVKw0cOFDvvfee2rVr59VY5s2bpyeffFKXXnqpEhMTlZubq7y8PDVv3lxJSUn6+uuvNXny5Ap9vrCwMM2fP18LFixQv379VL9+fWVkZKh+/frq16+fkpOT9cEHHyg0NLRC160ODz74oMLCwpSZmalJkya52mNjY/XVV1/p448/1t///nc1a9ZMOTk5ys7OVpMmTdSvXz9NnTq11AVr48aN008//aSRI0eqdevWkgrr3rZt21Y33XSTkpOT3WoE16lTxzVb2qJFCwUHByskJEQXX3yx5s6dq3//+9+n9ftQngEDBmjnzp166623NGjQINcYMzMz1bBhQ1166aV69tlntXPnTr388sslzr/99tu1ZMkS9e7d25X+0aZNG02aNEnLly/36UyvVJine+6557re33DDDeVW+UhMTNS6des0e/ZsXX311YqLi3OlICUmJuraa6/VzJkztWbNGp+OFfAXhmlWUW0YAAAAoJow0wsAAADLI+gFAACA5RH0AgAAwPIIegEAAGB5BL0AAACwPIJeAAAAWF5IdQ/AXxUUFGj//v2qXbu2DMOo7uEAAACgGNM0lZGRofj4eAUFlT2XS9Bbiv3796tZs2bVPQwAAACUY8+ePWratGmZfQh6S1G7dm1Jhd/EorsKAQAAwD+kp6erWbNmrritLAS9pXCmNMTExBD0AgAA+DFvUlFZyAYAAADLI+gFAACA5RH0AgAAwPLI6QUAAJZkmqZOnjyp/Pz86h4KTkFoaKiCg4NP+ToEvQAAwHJyc3Nlt9uVlZVV3UPBKTIMQ02bNlWtWrVO6ToEvQAAwFIKCgq0a9cuBQcHKz4+XmFhYWw0FaBM09ShQ4e0d+9enXHGGac040vQCwAALCU3N1cFBQVq1qyZoqKiqns4OEUNGjRQSkqK8vLyTinoZSEbAACwpPK2pUVg8NUsPf8aAAAAYHkEvQAAALA8gl4AAABYHkEvAACAnxg2bJgMw5BhGAoNDVXLli314IMPKjMzs9RznnjiCdc5QUFBio+P1+DBg7Vnz54qHLn/I+gFAAAog92RrdU70mR3ZFfJ/a644grZ7Xbt3LlTzzzzjKZNm6YHH3ywzHPat28vu92uvXv3av78+dq0aZNuuOGGKhlvUXl5eVV+T28R9AIAAMszTVNZuScr/HpvTYp6TFqmm9/6Xj0mLdN7a1IqfA3TNCs01vDwcDVu3FjNmjXTzTffrMGDB2vRokVlnhMSEqLGjRsrPj5ePXv21MiRI/W///1P6enpZZ63ePFidenSRREREYqNjdWgQYNcxwzDKHHfOnXqaNasWZKklJQUGYah//znP7r44osVERGhadOmKTIyUp9//rnbecnJyYqOjtbx48clSfv27VNSUpLq1q2r+vXra8CAAUpJSfHq+1NZAVGnd8WKFXrxxRe1fv162e12LVy4UAMHDizznOXLl2vMmDH69ddfFR8fr3/+858aNWpU1QwYAAD4ley8fJ312BendI0CU3r041/16Me/Vui8zU/1VVRY5UOuyMjICs2gpqamKjk5WcHBwWXWtf300081aNAgTZgwQe+9955yc3P16aefVnh8Dz/8sP71r3/pnXfeUXh4uFauXKk5c+boiiuucPX54IMPNGDAANWqVUtZWVm65JJL1LNnT61YsUIhISF65plndMUVV+jnn39WWFhYhcfgjYAIejMzM9WxY0fddtttuu6668rtv2vXLl155ZUaOXKk3n//fX333Xe688471aBBA6/Ory52R7Z2pWUqMTZaklxfx9ki3Y75+3vGzlgZu3+8D6SxBvrYgdPlhx9+0AcffKBLL720zH6bNm1SrVq1VFBQoOzswjSMe++9V9HR0aWe8+yzz+rGG2/Uk08+6Wrr2LFjhcc4evRotxniwYMHa+jQocrKylJUVJTS09P16aefasGCBZKkefPmKSgoSG+//barBu8777yjOnXq6Ntvv1WfPn0qPAZvBETQ269fP/Xr18/r/v/+97+VkJCgKVOmSJLatWundevW6aWXXvLboHfqsm3615dbVfwPIIakC1rW0/c7j8gMgPeMnbEydv94H0hjDcix7zoi05SCDGnioLOV1DVB8G+RocHa/FTfCp2T6jihyyYvV0GRf5hBhvTVmIvU2BZRoXtXxCeffKJatWrp5MmTysvL04ABA/Taa69p9+7dOuuss1z9xo8fr/Hjx0uS2rZtq8WLFysnJ0cff/yxPvzwQz377LNl3mfjxo0aOXJkhcbmSZcuXdzeX3XVVQoJCdHixYt14403asGCBapdu7YrmF2/fr22b9+u2rVru5134sQJ7dix45THUxrDrGiiSTUzDKPc9IZevXqpU6dOeuWVV1xtCxcu1A033KCsrCyFhoaWOCcnJ0c5OTmu9+np6WrWrJkcDodiYmJ8+hmKszuy1X3ishL/sQcA+L9gw9CqsZcw4+tHTpw4oV27dikxMVEREd4Hp57MX7tb45N/Ub5pKtgw9NygDqf1l5xhw4Zp3759mj59ukJDQxUfH++KW06ePOmW91qvXj3Vq1dPTzzxhBYtWqSNGze6jt122206efKk3nvvvVLvVb9+fb300ku67bbbPB4PCgrSggULdO2117raoqOj9frrr2vYsGFKSUlRYmKiNmzYoHPPPdft3JEjR+rAgQNavHixLr/8cp155pl67bXXJEn/+Mc/9OOPP2rOnDkl7tmgQQPZbDa3trKeZ3p6umw2m1fxWkDM9FZUamqqGjVq5NbWqFEjnTx5UmlpaYqLiytxzsSJE92m96vSrrRMAl4ACFD5pqmUtCyCXotK6pqgXm0aKCUtSy1io6rkOUdHR6t169Yl2kNCQjy2e/Loo4+qTZs2uv/++3Xeeed57HPOOefo66+/LjXobdCg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Ak888YQMwyjxCg8PV3x8vPr27au3335beXl51T1UALAkgl4AqGKNGjVyvUJCQmS32/Xll19q5MiR6t69u44ePVrdQwQAyyHoBYAqlpqa6nplZmbqjz/+0MiRIyVJ69at07333lvNIwQA6yHoBYBqlpCQoDfffFOXXnqpJOk///mPjh8/Xs2jAgBrIegFAD/Rt29fSVJubq62bdtW4viJEyf06quv6qKLLlJsbKzCwsLUuHFjDRw4UJ9//nm51//+++912223qXXr1oqOjlZMTIzOOussDR8+XF9++WWJ/j/++KOeeuop9erVS82bN1dERITq1KmjCy+8UM8//zyBOYCAElLdAwAAFDJN0/V1fn6+27Ft27bpqquucgXDhmEoJiZGBw4c0Mcff6yPP/5Y//jHPzRt2rQS183Pz9eYMWP06quvutqio6OVn5+vLVu2aMuWLUpOTtaxY8fczuvcubPr66CgIMXExOjYsWP6/vvv9f3332v27Nn65ptv1LBhQ198fAA4rZjpBQA/8cUXX0gqDGgTExNd7ceOHVOfPn20bds29e7dWytWrFB2draOHTumY8eOafLkyapVq5amT5+uV155pcR1x48f7wp4hw8frt9//13Hjx9XZmamDhw4oEWLFumKK64ocd5ll12mmTNn6o8//lBOTo6OHj2qrKwsJScnq23bttq8ebNGjRp1mr4bAOBjJgDgtHv88cdNSaan/+z+8ccf5siRI13H+/fv73b8wQcfNCWZvXv3NvPy8jxePzk52ZRkxsbGuvX5/fffzaCgIFOS+c9//tNnn2fv3r1meHi4aRiG+ccff5Q43rx5c1OS+c4771ToGACcLqQ3AEAVa9y4sevrjIwMZWVlud6feeaZbikKpmlq5syZkqQHHnhAISGe/7M9cOBAxcTEKC0tTevXr9cFF1wgSXr33XdVUFCg+vXr68knn/TZZ2jSpIk6duyoH374QatXr1ZCQoLPrg0ApwNBLwBUsQMHDnhsHzp0qN544w1FRES42jZv3qwjR45IkoYNG6agoNKz0pwLy/744w9X0Lt69WpJ0uWXX+52XW8UFBRo3rx5mjdvnjZu3KhDhw7pxIkTJfrt3bu3QtcFgOpA0AsAVcz8c8GaaZpKTU3V4sWLNXbsWM2ePVsdOnTQQw895Oq7f/9+19eHDh3y6vpFZ45TU1MlSc2bN6/QGLOysnT11Vfrm2++cbWFhYWpXr16Cg0NlSQdOXJEeXl5yszMrNC1AaA6sJANAKqJYRiKi4vTHXfcoYULF8owDD388MNatmyZq0/RKg6pqakyTbPc17BhwzzeqyKeffZZffPNN4qMjNTLL7+sP/74QydOnNDhw4ddG2s4Z5PNIlUnAMBfEfQCgB+4+OKLNWTIEJmmqbvvvtsV7BbN/920aVOFrxsXFydJSklJqdB58+bNkyQ99thjGj16tBISEkoEzs5ZZAAIBAS9AOAnHnvsMQUHB2vLli169913JUkdOnRQTEyMpL8C0Yro3r27JGnp0qUe83FLs2fPHklSp06dPB5PSUnR9u3bKzweAKguBL0A4CdatWqlpKQkSdLTTz+tvLw8hYSEaPjw4ZIKKzGsWrWqzGs4F705DRs2TMHBwTp8+LAef/xxr8dis9kkST/99JPH42PHjvX6WgDgDwh6AcCPjBs3ToZhKCUlRTNmzJAkPfroo2rVqpVOnjypK664QpMnT3Zb1OZwOPT555/r1ltvVc+ePd2u17p1a9fCuBdeeEEjRoxw2+L40KFDmj9/vq699lq385ybVTzzzDNKTk7WyZMnJUm7du3SzTffrP/85z+qW7eu778BAHCaEPQCgB/p0KGD+vfvL6lwMVlOTo7q1aunpUuXqmPHjsrMzNQDDzyghg0bqm7durLZbKpTp4769eun2bNnKzc3t8Q1n3nmGd11112SpBkzZqhNmzaqXbu2oqOj1bBhQ914441uVRqc5zRq1EgZGRm67rrrFBkZqTp16qhly5aaO3eunn32WZ1zzjmn/xsCAD5C0AsAfmbChAmSCuvfvvHGG5KkxMRErVu3TrNnz9bVV1+tuLg4ZWZmKjc3V4mJibr22ms1c+ZMrVmzpsT1goODNXXqVK1atUqDBw9WQkKC8vLyFBYWpvbt2+v222/XggUL3M5p3ry51q1bp9tvv13x8fGSpIiICF199dX64osvNG7cuNP8XQAA3zJMas0AAADA4pjpBQAAgOUR9AIAAMDyCHoBAABgeQS9AAAAsDyCXgAAAFgeQS8AAAAsj6AXAAAAlkfQCwAAAMsj6AUAAIDlEfQCAADA8gh6AQAAYHkEvQAAALA8gl4AAABY3v8D8En4uuB7ZQwAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 800x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sensitivity: 0.8750\n",
      "Specificity: 0.8590\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 800x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.datasets import make_moons\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score, roc_curve, auc, precision_recall_curve\n",
    "\n",
    "class MoonDataClassifier:\n",
    "    def __init__(self, n_samples=1000, noise=0.25, test_size=0.3, random_state=42):\n",
    "        self.n_samples = n_samples\n",
    "        self.noise = noise\n",
    "        self.test_size = test_size\n",
    "        self.random_state = random_state\n",
    "        self.X_train, self.X_test, self.y_train, self.y_test = self.prepare_data()\n",
    "        self.model = self.train_model()\n",
    "\n",
    "    def generate_data(self):\n",
    "        X, Y = make_moons(n_samples=self.n_samples, noise=self.noise, random_state=self.random_state)\n",
    "        return X, Y\n",
    "\n",
    "    def prepare_data(self):\n",
    "        X, Y = self.generate_data()\n",
    "        return train_test_split(X, Y, test_size=self.test_size, random_state=self.random_state)\n",
    "\n",
    "    def train_model(self):\n",
    "        model = LogisticRegression()\n",
    "        model.fit(self.X_train, self.y_train)\n",
    "        return model\n",
    "\n",
    "    def predict(self):\n",
    "        y_pred = self.model.predict(self.X_test)\n",
    "        y_prob = self.model.predict_proba(self.X_test)[:, 1]\n",
    "        return y_pred, y_prob\n",
    "\n",
    "    def evaluate(self):\n",
    "        y_pred, y_prob = self.predict()\n",
    "        self.print_confusion_matrix(y_pred)\n",
    "        self.plot_confusion_matrix(y_pred)\n",
    "        self.print_performance_metrics(y_pred)\n",
    "        self.plot_precision_recall_curve(y_prob)\n",
    "        self.print_sensitivity_specificity(y_pred)\n",
    "        self.plot_roc_curve(y_prob)\n",
    "\n",
    "    def print_confusion_matrix(self, y_pred):\n",
    "        cm = confusion_matrix(self.y_test, y_pred)\n",
    "        print(\"Confusion Matrix:\")\n",
    "        print(cm)\n",
    "        tn, fp, fn, tp = cm.ravel()\n",
    "        print(f\"True Negatives (TN): {tn}\")\n",
    "        print(f\"False Positives (FP): {fp}\")\n",
    "        print(f\"False Negatives (FN): {fn}\")\n",
    "        print(f\"True Positives (TP): {tp}\")\n",
    "\n",
    "    def plot_confusion_matrix(self, y_pred):\n",
    "        cm = confusion_matrix(self.y_test, y_pred)\n",
    "        plt.figure(figsize=(6, 6))\n",
    "        sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False)\n",
    "        plt.xlabel('Predicted Label', fontsize=18)\n",
    "        plt.ylabel('True Label', fontsize=18)\n",
    "        plt.title('Confusion Matrix', fontsize=18)\n",
    "        plt.savefig('confusion_matrix.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "    def print_performance_metrics(self, y_pred):\n",
    "        accuracy = accuracy_score(self.y_test, y_pred)\n",
    "        precision = precision_score(self.y_test, y_pred)\n",
    "        recall = recall_score(self.y_test, y_pred)\n",
    "        f1 = f1_score(self.y_test, y_pred)\n",
    "        print(f\"Accuracy: {accuracy:.4f}\")\n",
    "        print(f\"Precision: {precision:.4f}\")\n",
    "        print(f\"Recall: {recall:.4f}\")\n",
    "        print(f\"F1-Score: {f1:.4f}\")\n",
    "\n",
    "    def plot_precision_recall_curve(self, y_prob):\n",
    "        precision_vals, recall_vals, _ = precision_recall_curve(self.y_test, y_prob)\n",
    "        plt.figure(figsize=(8, 6))\n",
    "        plt.plot(recall_vals, precision_vals, marker='.', label='P-R curve')\n",
    "        plt.xlabel('Recall', fontsize=18)\n",
    "        plt.ylabel('Precision', fontsize=18)\n",
    "        plt.title('Precision-Recall Curve', fontsize=18)\n",
    "        plt.legend()\n",
    "        plt.savefig('precision_recall_curve.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "    def print_sensitivity_specificity(self, y_pred):\n",
    "        tn, fp, fn, tp = confusion_matrix(self.y_test, y_pred).ravel()\n",
    "        sensitivity = tp / (tp + fn)\n",
    "        specificity = tn / (tn + fp)\n",
    "        print(f\"Sensitivity: {sensitivity:.4f}\")\n",
    "        print(f\"Specificity: {specificity:.4f}\")\n",
    "\n",
    "    def plot_roc_curve(self, y_prob):\n",
    "        fpr, tpr, _ = roc_curve(self.y_test, y_prob)\n",
    "        roc_auc = auc(fpr, tpr)\n",
    "        plt.figure(figsize=(8, 6))\n",
    "        plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')\n",
    "        plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n",
    "        plt.xlim([0.0, 1.0])\n",
    "        plt.ylim([0.0, 1.05])\n",
    "        plt.xlabel('False Positive Rate', fontsize=18)\n",
    "        plt.ylabel('True Positive Rate', fontsize=18)\n",
    "        plt.title('Receiver Operating Characteristic', fontsize=18)\n",
    "        plt.legend(loc=\"lower right\")\n",
    "        plt.savefig('roc_curve.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    classifier = MoonDataClassifier()\n",
    "    classifier.evaluate()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "060ff8e9-ec1b-4651-8fed-8e6bc1755c5e",
   "metadata": {},
   "source": [
    "# 实验六"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "bf0c4be4-dbf0-4c4b-ad0a-83936140b3b1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGxCAYAAACwbLZkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACEmUlEQVR4nO3dd3hTZfvA8e9zku7JLHvJ3gKCgCxliAiCoigKLlRe9aeIEze++uLegAvcIi6ciOIAmQrIEFnKKquMlu6V5Dy/P0ILpUmarqRJ7891cWlPnpxz91B67jzjfpTWWiOEEEII4SeGvwMQQgghRPUmyYgQQggh/EqSESGEEEL4lSQjQgghhPArSUaEEEII4VeSjAghhBDCryQZEUIIIYRfSTIihBBCCL+SZEQIIYQQfiXJiBAV5NFHH0UpxbFjx8r1fsMw2LVrV7HXs7KyiI2NRSnFNddcU85oq4bDhw9z33330alTJ6KjowkPD6dVq1bcfvvt/PPPP4XtCu5NZVm4cCGPPvpopZ1/4MCBDBw4sNLOL0Sgs/o7ACFEUdHR0bz99tv897//LXL8008/xWazERIS4qfIKtYff/zBhRdeiNaaW2+9ld69exMaGsr27dv54IMP6NmzJ8ePH/dJLAsXLmTmzJmVlpDMmjWrUs4rRLCQZESIKmbcuHG8++67TJ8+HcM42Xk5Z84cxowZw9dff+3H6CpGeno6F110EeHh4axcuZJGjRoVvjZw4EBuuukmPvvsMz9GWDGys7OJjIykffv2/g5FiCpNhmmEqETbtm2jRYsW9OrViyNHjnj1nuuuu459+/axePHiwmM7duxg+fLlXHfddS7fk56ezl133UXz5s0JDQ2lYcOGTJkyhaysrCLtZs6cSf/+/albty5RUVF06tSJp59+GpvNVqTdwIED6dixI2vWrKFfv35ERkbSokULnnzySUzTLGxnmiaPP/44bdq0ISIigvj4eDp37sxLL73k8Xt88803SUpK4umnny6SiJxq7NixHs+hlHLZk9GsWbMiw1jZ2dmF9yY8PJyaNWvSo0cP5s2bB8A111zDzJkzC89Z8GfPnj0AaK2ZNWsWXbt2JSIigho1ajB27NhiQ2kF9+y3336jT58+REZGFv59nT5Ms2fPHpRSPPvsszz//PM0b96c6OhoevfuzerVq13er9atWxMWFkb79u356KOPuOaaa2jWrJnHeyREoJCeESEqydKlSxkzZgz9+/fno48+IjIy0qv3tWrVin79+jF37lyGDRsGwNy5c2nWrBnnnXdesfbZ2dkMGDCA/fv3c//999O5c2f+/vtvHn74Yf766y9++umnwvkWO3fuZPz48YVJy8aNG3niiSfYtm0bc+fOLXLepKQkrrzySu68804eeeQRFixYwLRp02jQoAETJ04E4Omnn+bRRx/lwQcfpH///thsNrZt20ZqaqrH7/HHH3/EYrEwcuRIr+5JeUydOpX333+fxx9/nDPPPJOsrCw2b95McnIyAA899BBZWVl89tlnrFq1qvB99evXB+Cmm27inXfe4bbbbuOpp54iJSWFxx57jD59+rBx40YSEhIK33Po0CGuuuoq7rnnHv73v/8V6dlyZebMmbRt25YXX3yxMJYLLriA3bt3ExcXB8Abb7zBTTfdxCWXXMILL7xAWloa06dPJy8vryJvkxD+pYUQFeKRRx7RgD569Kh+//33dWhoqL7tttu0w+Eo9fvffvttHRYWppOTk7Xdbtf169fXjz76qNZa66ioKH311VcXvm/GjBnaMAy9Zs2aIuf77LPPNKAXLlzo8noOh0PbbDb93nvvaYvFolNSUgpfGzBggAb077//XuQ97du318OGDSv8+sILL9Rdu3b16vs7Vdu2bXW9evW8bl9wb04F6EceeaRY26ZNmxa5Px07dtSjR4/2eP5bbrml2Pm11nrVqlUa0M8991yR4/v27dMRERH6nnvuKTxWcM9+/vnnYucZMGCAHjBgQOHXu3fv1oDu1KmTttvthcf/+OMPDeh58+ZprZ1/R/Xq1dO9evUqcr69e/fqkJAQ3bRpU4/flxCBQoZphKhgTzzxBNdccw1PPvkkL730UpFPx1pr7HZ7kT+uXHrppYSGhvLhhx+ycOFCkpKS3K6g+fbbb+nYsSNdu3Ytct5hw4ahlGLJkiWFbdevX8+oUaOoVasWFouFkJAQJk6ciMPhYMeOHUXOW69ePXr27FnkWOfOndm7d2/h1z179mTjxo3cfPPN/PDDD6Snp5fyblW+nj178v3333PfffexZMkScnJyvH7vt99+i1KKq666qsi9rVevHl26dClybwFq1KjBueee6/X5R4wYgcViKfy6c+fOAIX3ePv27SQlJXHZZZcVeV+TJk3o27ev19cRoqqTZESICvbBBx/QsGFDLr/88mKvvfvuu4SEhBT540pUVBTjxo1j7ty5zJkzh8GDB9O0aVOXbQ8fPsymTZuKnTcmJgatdeFS48TERPr168eBAwd46aWXWLZsGWvWrCmcL3H6Q7pWrVrFrhUWFlak3bRp03j22WdZvXo1w4cPp1atWpx33nmsXbvW4z1q0qQJR48eLTanpTK8/PLL3HvvvXz55ZcMGjSImjVrMnr06CJLh905fPgwWmsSEhKK3d/Vq1cXW8ZdMLTjrdPvcVhYGHDy76JgKOnUoaACro4JEahkzogQFWzRokWMGzeOfv368fPPPxdJIkaOHMmaNWu8Os91113HW2+9xaZNm/jwww/dtqtduzYRERHF5nyc+jrAl19+SVZWFl988UWRmDZs2OBVPK5YrVamTp3K1KlTSU1N5aeffuL+++9n2LBh7Nu3z+08mWHDhvHjjz/yzTffuEzavBEWFuZy3kTBA7xAVFQU06dPZ/r06Rw+fLiwl2TkyJFs27bN4zVq166NUoply5YVJgqnx3Cqiq6FUpCsHD58uNhrSUlJFXotIfxJekaEqGBNmzYtfHj169evyCfwWrVq0aNHjyJ/3OnduzfXXXcdY8aMYcyYMW7bXXjhhezcudPluXv06FG44qLgQXnqA1RrzZtvvlnO79gpPj6esWPHcsstt5CSklK4GsWV66+/nnr16nHPPfdw4MABl22++OILj9dr1qwZmzZtKnLsl19+ITMz0+17EhISuOaaa7jiiivYvn072dnZQPEeiQIFdVAOHDjg8t526tTJY4zl1aZNG+rVq8cnn3xS5HhiYiIrV66s1GsL4UvSMyJEJahfvz5Lly5l2LBh9O/fn8WLF9OxY8dSn2fOnDkltpkyZQqff/45/fv354477qBz586YpkliYiI//vgjd955J7169WLIkCGEhoZyxRVXcM8995Cbm8vs2bPLVVhs5MiRdOzYkR49elCnTh327t3Liy++SNOmTWnVqpXb98XFxfHVV19x4YUXcuaZZxYpevbPP//wwQcfsHHjRi6++GK355gwYQIPPfQQDz/8MAMGDGDLli28+uqrhatQCvTq1YsLL7yQzp07U6NGDbZu3cr7779P7969C3tuCpKKp556iuHDh2OxWOjcuTN9+/blxhtv5Nprr2Xt2rX079+fqKgoDh06xPLly+nU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+IIhQ4ZQp04dYmNj6d27Nz/88IMPow18pf35LrBixQqsVitdu3at3ACDTGnvd15eHg888ABNmzYlLCyMM844g7lz5/oo2sBX2vv94Ycf0qVLFyIjI6lfvz7XXnstycnJPoo2cP3222+MHDmSBg0aoJTiyy+/LPE9lfas1EHo448/1iEhIfrNN9/UW7Zs0bfffruOiorSe/fuddl+165dOjIyUt9+++16y5Yt+s0339QhISH6s88+83Hkgam09/v222/XTz31lP7jjz/0jh079LRp03RISIj+888/fRx5YCrt/S6QmpqqW7RooYcOHaq7dOnim2CDQFnu96hRo3SvXr304sWL9e7du/Xvv/+uV6xY4cOoA1dp7/eyZcu0YRj6pZde0rt27dLLli3THTp00KNHj/Zx5IFn4cKF+oEHHtCff/65BvSCBQs8tq/MZ2VQJiM9e/bUkydPLnKsbdu2+r777nPZ/p577tFt27Ytcuymm27SZ599dqXFGExKe79dad++vZ4+fXpFhxaUynq/x40bpx988EH9yCOPSDJSCqW9399//72Oi4vTycnJvggv6JT2fj/zzDO6RYsWRY69/PLLulGjRpUWYzDyJhmpzGdl0A3T5Ofns27dOoYOHVrk+NChQ1m5cqXL96xatapY+2HDhrF27VpsNlulxRoMynK/T2eaJhkZGdSsWbMyQgwqZb3fb7/9Njt37uSRRx6p7BCDSlnu99dff02PHj14+umnadiwIa1bt+auu+4iJyfHFyEHtLLc7z59+rB//34WLlyI1prDhw/z2WefMWLECF+EXK1U5rMyIHbtLY1jx47hcDhISEgocjwhIYGkpCSX70lKSnLZ3m63c+zYMerXr19p8Qa6stzv0z333HNkZWVx2WWXVUaIQaUs9/uff/7hvvvuY9myZVitQfdPvlKV5X7v2rWL5cuXEx4ezoIFCzh27Bg333wzKSkpMm+kBGW533369OHDDz9k3Lhx5ObmYrfbGTVqFK+88oovQq5WKvNZGXQ9IwWUUkW+1loXO1ZSe1fHhWulvd8F5s2bx6OPPsr8+fOpW7duZYUXdLy93w6Hg/HjxzN9+nRat27tq/CCTml+vk3TRCnFhx9+SM+ePbngggt4/vnneeedd6R3xEulud9btmzhtttu4+GHH2bdunUsWrSI3bt3M3nyZF+EWu1U1rMy6D4m1a5dG4vFUiyLPnLkSLGMrkC9evVctrdardSqVavSYg0GZbnfBebPn8/111/Pp59+yuDBgyszzKBR2vudkZHB2rVrWb9+PbfeeivgfFhqrbFarfz444+ce+65Pok9EJXl57t+/fo0bNiQuLi4wmPt2rVDa83+/ftp1apVpcYcyMpyv2fMmEHfvn25++67AejcuTNRUVH069ePxx9/XHq2K1BlPiuDrmckNDSU7t27s3jx4iLHFy9eTJ8+fVy+p3fv3sXa//jjj/To0YOQkJBKizUYlOV+g7NH5JprruGjjz6Ssd1SKO39jo2N5a+//mLDhg2FfyZPnkybNm3YsGEDvXr18lXoAaksP999+/bl4MGDZGZmFh7bsWMHhmHQqFGjSo030JXlfmdnZ2MYRR9lFosFOPmpXVSMSn1WlnsKbBVUsDRszpw5esuWLXrKlCk6KipK79mzR2ut9X333acnTJhQ2L5gudIdd9yht2zZoufMmSNLe0uhtPf7o48+0larVc+cOVMfOnSo8E9qaqq/voWAUtr7fTpZTVM6pb3fGRkZulGjRnrs2LH677//1kuXLtWtWrXSkyZN8te3EFBKe7/ffvttbbVa9axZs/TOnTv18uXLdY8ePXTPnj399S0EjIyMDL1+/Xq9fv16Dejnn39er1+/vnAZtS+flUGZjGit9cyZM3XTpk11aGio7tatm166dGnha1dffbUeMGBAkfZLlizRZ555pg4NDdXNmjXTs2fP9nHEga0093vAgAEaKPbn6quv9n3gAaq0P9+nkmSk9Ep7v7du3aoHDx6sIyIidKNGjfTUqVN1dna2j6MOXKW93y+//LJu3769joiI0PXr19dXXnml3r9/v4+jDjy//vqrx9/FvnxWKq2lH0sIIYQQ/hN0c0aEEEIIEVgkGRFCCCGEX0kyIoQQQgi/kmRECCGEEH4lyYgQQggh/EqSESGEEEL4lSQjQgghhPArSUaEEEII4VeSjAghhBDCryQZEUIIIYRfSTIihBBCCL/6fwD1djZnlTzvAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: 'path_to_your_image.png'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[2], line 90\u001b[0m\n\u001b[0;32m     88\u001b[0m segmenter \u001b[38;5;241m=\u001b[39m ImageSegmenter()\n\u001b[0;32m     89\u001b[0m image_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpath_to_your_image.png\u001b[39m\u001b[38;5;124m'\u001b[39m  \u001b[38;5;66;03m# 替换为你的图像路径\u001b[39;00m\n\u001b[1;32m---> 90\u001b[0m segmenter\u001b[38;5;241m.\u001b[39msegment_image_background(image_path, k\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2\u001b[39m)\n\u001b[0;32m     92\u001b[0m compressor \u001b[38;5;241m=\u001b[39m ImageCompressor()\n\u001b[0;32m     93\u001b[0m compressor\u001b[38;5;241m.\u001b[39mcompress_image(image_path, k\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m16\u001b[39m)\n",
      "Cell \u001b[1;32mIn[2], line 30\u001b[0m, in \u001b[0;36mImageSegmenter.segment_image_background\u001b[1;34m(self, image_path, k)\u001b[0m\n\u001b[0;32m     29\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21msegment_image_background\u001b[39m(\u001b[38;5;28mself\u001b[39m, image_path, k\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2\u001b[39m):\n\u001b[1;32m---> 30\u001b[0m     image \u001b[38;5;241m=\u001b[39m imread(image_path)\n\u001b[0;32m     31\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m image\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m4\u001b[39m:\n\u001b[0;32m     32\u001b[0m         image \u001b[38;5;241m=\u001b[39m image[:, :, :\u001b[38;5;241m3\u001b[39m]\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\matplotlib\\image.py:1544\u001b[0m, in \u001b[0;36mimread\u001b[1;34m(fname, format)\u001b[0m\n\u001b[0;32m   1537\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(fname, \u001b[38;5;28mstr\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(parse\u001b[38;5;241m.\u001b[39murlparse(fname)\u001b[38;5;241m.\u001b[39mscheme) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[0;32m   1538\u001b[0m     \u001b[38;5;66;03m# Pillow doesn't handle URLs directly.\u001b[39;00m\n\u001b[0;32m   1539\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m   1540\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPlease open the URL for reading and pass the \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1541\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresult to Pillow, e.g. with \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1542\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m``np.array(PIL.Image.open(urllib.request.urlopen(url)))``.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1543\u001b[0m         )\n\u001b[1;32m-> 1544\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m img_open(fname) \u001b[38;5;28;01mas\u001b[39;00m image:\n\u001b[0;32m   1545\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m (_pil_png_to_float_array(image)\n\u001b[0;32m   1546\u001b[0m             \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(image, PIL\u001b[38;5;241m.\u001b[39mPngImagePlugin\u001b[38;5;241m.\u001b[39mPngImageFile) \u001b[38;5;28;01melse\u001b[39;00m\n\u001b[0;32m   1547\u001b[0m             pil_to_array(image))\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\PIL\\ImageFile.py:126\u001b[0m, in \u001b[0;36mImageFile.__init__\u001b[1;34m(self, fp, filename)\u001b[0m\n\u001b[0;32m    122\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdecodermaxblock \u001b[38;5;241m=\u001b[39m MAXBLOCK\n\u001b[0;32m    124\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_path(fp):\n\u001b[0;32m    125\u001b[0m     \u001b[38;5;66;03m# filename\u001b[39;00m\n\u001b[1;32m--> 126\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(fp, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrb\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m    127\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfilename \u001b[38;5;241m=\u001b[39m fp\n\u001b[0;32m    128\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exclusive_fp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'path_to_your_image.png'"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.image import imread\n",
    "from sklearn.cluster import KMeans\n",
    "\n",
    "class KMeansClusterer:\n",
    "    def __init__(self, random_state=42):\n",
    "        np.random.seed(random_state)\n",
    "\n",
    "    def kmeans_clustering(self, X, k, max_iter=100):\n",
    "        centroids = X[np.random.choice(X.shape[0], k, replace=False)]\n",
    "        for iteration in range(max_iter):\n",
    "            distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)\n",
    "            labels = np.argmin(distances, axis=1)\n",
    "            new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(k)])\n",
    "            if np.all(centroids == new_centroids):\n",
    "                break\n",
    "            centroids = new_centroids\n",
    "        return labels, centroids\n",
    "\n",
    "    def plot_clustering_results(self, X, labels, centroids):\n",
    "        plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')\n",
    "        plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='x')\n",
    "        plt.title('k-Means Clustering')\n",
    "        plt.savefig('clustering_results.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "class ImageSegmenter(KMeansClusterer):\n",
    "    def segment_image_background(self, image_path, k=2):\n",
    "        image = imread(image_path)\n",
    "        if image.ndim == 4:\n",
    "            image = image[:, :, :3]\n",
    "        image = image / 255.0\n",
    "        pixels = image.reshape(-1, 3)\n",
    "        labels, _ = self.kmeans_clustering(pixels, k)\n",
    "        segmented_image = labels.reshape(image.shape[:2])\n",
    "        self.plot_image_segmentation(image, segmented_image)\n",
    "\n",
    "    def plot_image_segmentation(self, original_image, segmented_image):\n",
    "        plt.figure(figsize=(12, 6))\n",
    "        plt.subplot(1, 2, 1)\n",
    "        plt.imshow(original_image)\n",
    "        plt.title('Original Image')\n",
    "        plt.axis('off')\n",
    "        plt.subplot(1, 2, 2)\n",
    "        plt.imshow(segmented_image, cmap='gray')\n",
    "        plt.title('Segmented Image')\n",
    "        plt.axis('off')\n",
    "        plt.savefig('segmented_image.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "class ImageCompressor(KMeansClusterer):\n",
    "    def compress_image(self, image_path, k=16):\n",
    "        image = imread(image_path)\n",
    "        if image.ndim == 4:\n",
    "            image = image[:, :, :3]\n",
    "        image = image / 255.0\n",
    "        pixels = image.reshape(-1, 3)\n",
    "        kmeans = KMeans(n_clusters=k, random_state=42)\n",
    "        kmeans.fit(pixels)\n",
    "        labels = kmeans.predict(pixels)\n",
    "        centroids = kmeans.cluster_centers_\n",
    "        compressed_pixels = centroids[labels]\n",
    "        compressed_image = compressed_pixels.reshape(image.shape)\n",
    "        self.plot_image_compression(image, compressed_image)\n",
    "\n",
    "    def plot_image_compression(self, original_image, compressed_image):\n",
    "        plt.figure(figsize=(12, 6))\n",
    "        plt.subplot(1, 2, 1)\n",
    "        plt.imshow(original_image)\n",
    "        plt.title('Original Image')\n",
    "        plt.axis('off')\n",
    "        plt.subplot(1, 2, 2)\n",
    "        plt.imshow(compressed_image)\n",
    "        plt.title('Compressed Image')\n",
    "        plt.axis('off')\n",
    "        plt.savefig('compressed_image.png', dpi=300)\n",
    "        plt.show()\n",
    "\n",
    "# 示例用法\n",
    "if __name__ == \"__main__\":\n",
    "    clusterer = KMeansClusterer()\n",
    "    X = np.random.rand(100, 2)  # 生成随机数据\n",
    "    k = 3\n",
    "    labels, centroids = clusterer.kmeans_clustering(X, k)\n",
    "    clusterer.plot_clustering_results(X, labels, centroids)\n",
    "\n",
    "    segmenter = ImageSegmenter()\n",
    "    image_path = 'path_to_your_image.png'  # 替换为你的图像路径\n",
    "    segmenter.segment_image_background(image_path, k=2)\n",
    "\n",
    "    compressor = ImageCompressor()\n",
    "    compressor.compress_image(image_path, k=16)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a21842b9-14a3-46b6-aa19-fe28ae79d0ef",
   "metadata": {},
   "source": [
    "# 实验七"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "28c6a921-d2a2-46da-ab5b-daa258a3d98c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGxCAYAAABvIsx7AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAADJZklEQVR4nOzddZxU1fvA8c+5M7Mz20U3KiAlIiClgKIgiAIGWAgiWPws1K9iN4oFBmIgiIGoCKgopSKC2KIoFkopzXZO3PP74y7LLju1HTzv12tfMPeee+4zGzPPnFRaa40QQgghRB1iVHcAQgghhBAVTRIcIYQQQtQ5kuAIIYQQos6RBEcIIYQQdY4kOEIIIYSocyTBEUIIIUSdIwmOEEIIIeocSXCEEEIIUedIgiOEEEKIOkcSHCFqqLlz56KUKvxyuVw0atSIU045halTp7J3794S19x7773FrjEMg8aNGzN06FDWrVtXovzXX3/NyJEjadGiBU6nk4YNG9K7d29uuummEmVN0+S1117jtNNOo169ejgcDho0aMCwYcP44IMPME2zxDUbN25EKYXD4WDXrl1+n+eAAQNQSnHGGWeUOLd161aUUjz++OPhfMvIyMjgoYceonv37sTFxeF0OmnVqhXjx4/nhx9+KCx38Hu7devWsOotrS+//JJ7772XtLS0Sql/3LhxtGrVqlLqFqKukARHiBpuzpw5rF+/npUrV/Lcc89x/PHH8+ijj9K+fXtWrVrl95ply5axfv161q5dy1NPPcXu3bsZMGBAsTf5pUuX0qdPHzIyMpg2bRorVqxgxowZ9O3blwULFhSrLy8vj6FDhzJ27FgaNGjA888/z6effsqsWbNo0qQJ559/Ph988EGJOF5++WUAvF4v8+bNC/o8ly9fzqefflrab0+hv//+m65du/LII49wyimnMH/+fFasWMF9993Hnj176NatG+np6WWuvzS+/PJL7rvvvkpLcO666y4WLVpUKXULUWdoIUSNNGfOHA3ob7/9tsS5bdu26ebNm+vY2Fi9e/fuwuP33HOPBvS+ffuKlf/77781oKdMmVJ4rF+/fvroo4/WHo+nRP0+n6/Y46uvvloD+tVXX/Ub659//ql/+umnYsfy8vJ0cnKy7tKli27atKlu27at32v79++v27Ztq4866ijdrVs3bZpm4bktW7ZoQD/22GN+rz3I6/Xqzp0767i4OL1x40a/ZT766COdnZ2ttT70vd2yZUvQesvqscceq5T6D8YvhAhNWnCEqIVatGjBE088QWZmJi+88ELI8vHx8QA4HI7CYwcOHKBevXrY7fYS5Q3j0EvD7t27efnllxk8eDCXXnqp3/rbtGnDcccdV+zY4sWLOXDgABMmTGDs2LH8+eefrF271u/1DoeDhx56iO+//75E61E4Fi9ezMaNG5kyZQqdOnXyW2bIkCFERUUFrKNVq1aMGzeuxPEBAwYwYMCAwsemafLggw/Srl07IiMjSUhI4LjjjmPGjBmA1U14yy23ANC6devC7sLVq1cX1rFgwQJ69+5NdHQ0MTExDB48mB9//LHYfceNG0dMTAwbN25k0KBBxMbGMnDgwMJzh3dRKaX4v//7P1577TXat29PVFQUXbp04cMPPyzxnJYsWcJxxx2H0+nkqKOOYsaMGYXdm0LUFZLgCFFLDR06FJvNxpo1a0qc8/l8eL1e3G43mzdvZtKkSTidTs4777zCMr179+brr7/muuuu4+uvv8bj8fi9z2effYbH42HEiBGlim/27Nk4nU4uvvhixo8fj1KK2bNnByw/evRounXrxp133hkwlkBWrFgBUOoYy2LatGnce++9XHjhhSxdupQFCxZw+eWXF3ZHTZgwgWuvvRaA9957j/Xr17N+/XpOOOEEAB5++GEuvPBCOnTowNtvv81rr71GZmYmJ598Mps2bSp2L7fbzdlnn82pp57KkiVLuO+++4LGtnTpUp599lnuv/9+Fi5cSFJSEiNHjuSff/4pLLNs2TLOOecckpOTWbBgAdOmTWP+/Pm8+uqrFfhdEqIGqO4mJCGEf8G6qA5q2LChbt++feHjg11Uh3/FxcXp9957r9i1+/fv1yeddFJhGYfDofv06aOnTp2qMzMzC8s98sgjGtDLli0LO/atW7dqwzD0BRdcUHisf//+Ojo6WmdkZBQr279/f92xY0ettdarVq3SgH7mmWe01uF3UZ1xxhka0Hl5eWHF56+LqmXLlnrs2LElyvbv31/379+/8PGwYcP08ccfH7T+QF1U27dv13a7XV977bXFjmdmZupGjRrpUaNGFR4bO3asBvQrr7xSov6xY8fqli1bFjsG6IYNGxb7/u7evVsbhqGnTp1aeKxHjx66efPmOj8/v9j9k5OTtbwliLpE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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.datasets import make_moons\n",
    "\n",
    "class DBSCAN:\n",
    "    def __init__(self, eps, min_samples):\n",
    "        self.eps = eps\n",
    "        self.min_samples = min_samples\n",
    "\n",
    "    def fit(self, data):\n",
    "        self.labels_ = np.zeros(data.shape[0], dtype=int)\n",
    "        self.cluster_id_ = 1\n",
    "        for i in range(data.shape[0]):\n",
    "            if self.labels_[i] != 0:\n",
    "                continue\n",
    "            neighbors = self.region_query(data, i)\n",
    "            if len(neighbors) < self.min_samples:\n",
    "                self.labels_[i] = -1  # 噪声点\n",
    "            else:\n",
    "                self.labels_[i] = self.cluster_id_\n",
    "                seeds = [i]\n",
    "                while seeds:\n",
    "                    current = seeds.pop(0)\n",
    "                    for j in self.region_query(data, current):\n",
    "                        if self.labels_[j] == 0:\n",
    "                            self.labels_[j] = self.cluster_id_\n",
    "                            seeds.append(j)\n",
    "                        elif self.labels_[j] == -1:\n",
    "                            self.labels_[j] = self.cluster_id_\n",
    "                self.cluster_id_ += 1\n",
    "        return self.labels_\n",
    "\n",
    "    def region_query(self, data, point_index):\n",
    "        return [idx for idx in range(data.shape[0]) if np.linalg.norm(data[point_index] - data[idx]) < self.eps]\n",
    "\n",
    "def plot_clustering_results(X, labels):\n",
    "    plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')\n",
    "    plt.title('DBSCAN Clustering')\n",
    "    plt.savefig('dbscan_clustering.png', dpi=300)\n",
    "    plt.show()\n",
    "\n",
    "# 示例用法\n",
    "if __name__ == \"__main__\":\n",
    "    X, _ = make_moons(n_samples=300, noise=0.05, random_state=42)\n",
    "    dbscan = DBSCAN(eps=0.2, min_samples=5)\n",
    "    labels = dbscan.fit(X)\n",
    "    plot_clustering_results(X, labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bab8dbc-8883-4825-9afc-ac4a7394cf9f",
   "metadata": {},
   "source": [
    "# 实验八"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a6bd9ca0-584c-4c3b-8784-3fe396189534",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n",
      "Epoch [1/5], Loss: 1.2305\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[8], line 123\u001b[0m\n\u001b[0;32m    120\u001b[0m     save_model(model)\n\u001b[0;32m    122\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[1;32m--> 123\u001b[0m     main()\n",
      "Cell \u001b[1;32mIn[8], line 116\u001b[0m, in \u001b[0;36mmain\u001b[1;34m()\u001b[0m\n\u001b[0;32m    114\u001b[0m trainloader, testloader \u001b[38;5;241m=\u001b[39m load_data()\n\u001b[0;32m    115\u001b[0m model, criterion, optimizer \u001b[38;5;241m=\u001b[39m create_model()\n\u001b[1;32m--> 116\u001b[0m train_losses \u001b[38;5;241m=\u001b[39m train_model(model, trainloader, criterion, optimizer, epochs\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m5\u001b[39m)\n\u001b[0;32m    117\u001b[0m plot_train_loss(train_losses)\n\u001b[0;32m    118\u001b[0m test_model(model, testloader)\n",
      "Cell \u001b[1;32mIn[8], line 58\u001b[0m, in \u001b[0;36mtrain_model\u001b[1;34m(model, trainloader, criterion, optimizer, epochs)\u001b[0m\n\u001b[0;32m     56\u001b[0m model\u001b[38;5;241m.\u001b[39mtrain()\n\u001b[0;32m     57\u001b[0m running_loss \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.0\u001b[39m\n\u001b[1;32m---> 58\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m images, labels \u001b[38;5;129;01min\u001b[39;00m trainloader:\n\u001b[0;32m     59\u001b[0m     optimizer\u001b[38;5;241m.\u001b[39mzero_grad()\n\u001b[0;32m     60\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m model(images)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:631\u001b[0m, in \u001b[0;36m_BaseDataLoaderIter.__next__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    628\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sampler_iter \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    629\u001b[0m     \u001b[38;5;66;03m# TODO(https://github.com/pytorch/pytorch/issues/76750)\u001b[39;00m\n\u001b[0;32m    630\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reset()  \u001b[38;5;66;03m# type: ignore[call-arg]\u001b[39;00m\n\u001b[1;32m--> 631\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_next_data()\n\u001b[0;32m    632\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m    633\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_kind \u001b[38;5;241m==\u001b[39m _DatasetKind\u001b[38;5;241m.\u001b[39mIterable \u001b[38;5;129;01mand\u001b[39;00m \\\n\u001b[0;32m    634\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \\\n\u001b[0;32m    635\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called:\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:675\u001b[0m, in \u001b[0;36m_SingleProcessDataLoaderIter._next_data\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    673\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_next_data\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m    674\u001b[0m     index \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_next_index()  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[1;32m--> 675\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_fetcher\u001b[38;5;241m.\u001b[39mfetch(index)  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[0;32m    676\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pin_memory:\n\u001b[0;32m    677\u001b[0m         data \u001b[38;5;241m=\u001b[39m _utils\u001b[38;5;241m.\u001b[39mpin_memory\u001b[38;5;241m.\u001b[39mpin_memory(data, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pin_memory_device)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\_utils\\fetch.py:51\u001b[0m, in \u001b[0;36m_MapDatasetFetcher.fetch\u001b[1;34m(self, possibly_batched_index)\u001b[0m\n\u001b[0;32m     49\u001b[0m         data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset\u001b[38;5;241m.\u001b[39m__getitems__(possibly_batched_index)\n\u001b[0;32m     50\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m---> 51\u001b[0m         data \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset[idx] \u001b[38;5;28;01mfor\u001b[39;00m idx \u001b[38;5;129;01min\u001b[39;00m possibly_batched_index]\n\u001b[0;32m     52\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m     53\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset[possibly_batched_index]\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\datasets\\cifar.py:119\u001b[0m, in \u001b[0;36mCIFAR10.__getitem__\u001b[1;34m(self, index)\u001b[0m\n\u001b[0;32m    116\u001b[0m img \u001b[38;5;241m=\u001b[39m Image\u001b[38;5;241m.\u001b[39mfromarray(img)\n\u001b[0;32m    118\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 119\u001b[0m     img \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform(img)\n\u001b[0;32m    121\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtarget_transform \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    122\u001b[0m     target \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtarget_transform(target)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\transforms.py:95\u001b[0m, in \u001b[0;36mCompose.__call__\u001b[1;34m(self, img)\u001b[0m\n\u001b[0;32m     93\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, img):\n\u001b[0;32m     94\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransforms:\n\u001b[1;32m---> 95\u001b[0m         img \u001b[38;5;241m=\u001b[39m t(img)\n\u001b[0;32m     96\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m img\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\transforms.py:137\u001b[0m, in \u001b[0;36mToTensor.__call__\u001b[1;34m(self, pic)\u001b[0m\n\u001b[0;32m    129\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, pic):\n\u001b[0;32m    130\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    131\u001b[0m \u001b[38;5;124;03m    Args:\u001b[39;00m\n\u001b[0;32m    132\u001b[0m \u001b[38;5;124;03m        pic (PIL Image or numpy.ndarray): Image to be converted to tensor.\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    135\u001b[0m \u001b[38;5;124;03m        Tensor: Converted image.\u001b[39;00m\n\u001b[0;32m    136\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[1;32m--> 137\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m F\u001b[38;5;241m.\u001b[39mto_tensor(pic)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\functional.py:174\u001b[0m, in \u001b[0;36mto_tensor\u001b[1;34m(pic)\u001b[0m\n\u001b[0;32m    172\u001b[0m img \u001b[38;5;241m=\u001b[39m img\u001b[38;5;241m.\u001b[39mview(pic\u001b[38;5;241m.\u001b[39msize[\u001b[38;5;241m1\u001b[39m], pic\u001b[38;5;241m.\u001b[39msize[\u001b[38;5;241m0\u001b[39m], F_pil\u001b[38;5;241m.\u001b[39mget_image_num_channels(pic))\n\u001b[0;32m    173\u001b[0m \u001b[38;5;66;03m# put it from HWC to CHW format\u001b[39;00m\n\u001b[1;32m--> 174\u001b[0m img \u001b[38;5;241m=\u001b[39m img\u001b[38;5;241m.\u001b[39mpermute((\u001b[38;5;241m2\u001b[39m, \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m))\u001b[38;5;241m.\u001b[39mcontiguous()\n\u001b[0;32m    175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(img, torch\u001b[38;5;241m.\u001b[39mByteTensor):\n\u001b[0;32m    176\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m img\u001b[38;5;241m.\u001b[39mto(dtype\u001b[38;5;241m=\u001b[39mdefault_float_dtype)\u001b[38;5;241m.\u001b[39mdiv(\u001b[38;5;241m255\u001b[39m)\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "class CIFAR10DataLoader:\n",
    "    def __init__(self, batch_size=32):\n",
    "        self.transform = transforms.Compose([\n",
    "            transforms.ToTensor(),\n",
    "            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n",
    "        ])\n",
    "        self.trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=self.transform)\n",
    "        self.testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=self.transform)\n",
    "        self.trainloader = torch.utils.data.DataLoader(self.trainset, batch_size=batch_size, shuffle=True)\n",
    "        self.testloader = torch.utils.data.DataLoader(self.testset, batch_size=batch_size, shuffle=False)\n",
    "\n",
    "class ConvNet(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(ConvNet, self).__init__()\n",
    "        self.layer1 = nn.Sequential(\n",
    "            nn.Conv2d(3, 32, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(2, 2)\n",
    "        )\n",
    "        self.layer2 = nn.Sequential(\n",
    "            nn.Conv2d(32, 64, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(2, 2)\n",
    "        )\n",
    "        self.fc1 = nn.Linear(64 * 8 * 8, 512)\n",
    "        self.fc2 = nn.Linear(512, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.layer1(x)\n",
    "        x = self.layer2(x)\n",
    "        x = x.view(-1, 64 * 8 * 8)\n",
    "        x = torch.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n",
    "class Trainer:\n",
    "    def __init__(self, model, trainloader, criterion, optimizer, epochs):\n",
    "        self.model = model\n",
    "        self.trainloader = trainloader\n",
    "        self.criterion = criterion\n",
    "        self.optimizer = optimizer\n",
    "        self.epochs = epochs\n",
    "\n",
    "    def train(self):\n",
    "        train_losses = []\n",
    "        for epoch in range(self.epochs):\n",
    "            self.model.train()\n",
    "            running_loss = 0.0\n",
    "            for images, labels in self.trainloader:\n",
    "                self.optimizer.zero_grad()\n",
    "                outputs = self.model(images)\n",
    "                loss = self.criterion(outputs, labels)\n",
    "                loss.backward()\n",
    "                self.optimizer.step()\n",
    "                running_loss += loss.item()\n",
    "            train_losses.append(running_loss / len(self.trainloader))\n",
    "            print(f'Epoch [{epoch+1}/{self.epochs}], Loss: {running_loss/len(self.trainloader):.4f}')\n",
    "        return train_losses\n",
    "\n",
    "class Tester:\n",
    "    def __init__(self, model, testloader):\n",
    "        self.model = model\n",
    "        self.testloader = testloader\n",
    "\n",
    "    def test(self):\n",
    "        self.model.eval()\n",
    "        correct = 0\n",
    "        total = 0\n",
    "        with torch.no_grad():\n",
    "            for images, labels in self.testloader:\n",
    "                outputs = self.model(images)\n",
    "                _, predicted = torch.max(outputs, 1)\n",
    "                total += labels.size(0)\n",
    "                correct += (predicted == labels).sum().item()\n",
    "        accuracy = 100 * correct / total\n",
    "        print(f'Accuracy of the model on the 10000 test images: {accuracy:.2f}%')\n",
    "        return accuracy\n",
    "\n",
    "class Plotter:\n",
    "    @staticmethod\n",
    "    def plot_train_loss(train_losses):\n",
    "        plt.plot(range(1, len(train_losses) + 1), train_losses)\n",
    "        plt.xlabel('Epoch')\n",
    "        plt.ylabel('Loss')\n",
    "        plt.title('Training Loss Curve')\n",
    "        plt.savefig('training_loss_curve.png')\n",
    "        plt.show()\n",
    "\n",
    "    @staticmethod\n",
    "    def show_test_images(model, testloader):\n",
    "        dataiter = iter(testloader)\n",
    "        images, labels = next(dataiter)\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        fig = plt.figure(figsize=(8, 8))\n",
    "        for idx in range(6):\n",
    "            ax = fig.add_subplot(2, 3, idx + 1)\n",
    "            ax.imshow(images[idx].numpy().transpose((1, 2, 0)))\n",
    "            ax.set_title(f'Label: {labels[idx].item()}, Pred: {predicted[idx].item()}')\n",
    "            ax.axis('off')\n",
    "        plt.savefig('sample_test_images_with_predictions.png')\n",
    "        plt.show()\n",
    "\n",
    "class ModelSaver:\n",
    "    @staticmethod\n",
    "    def save_model(model):\n",
    "        torch.save(model.state_dict(), 'cifar10_cnn_model.pth')\n",
    "\n",
    "def main():\n",
    "    data_loader = CIFAR10DataLoader()\n",
    "    model = ConvNet()\n",
    "    criterion = nn.CrossEntropyLoss()\n",
    "    optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
    "    trainer = Trainer(model, data_loader.trainloader, criterion, optimizer, epochs=5)\n",
    "    train_losses = trainer.train()\n",
    "    Plotter.plot_train_loss(train_losses)\n",
    "    tester = Tester(model, data_loader.testloader)\n",
    "    tester.test()\n",
    "    Plotter.show_test_images(model, data_loader.testloader)\n",
    "    ModelSaver.save_model(mod"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fab6f35-9385-4eb1-98c3-0be41781a7ac",
   "metadata": {},
   "source": [
    "# 实验九"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ecf585da-6677-4830-9d8f-24c2b91502fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/5], Loss: 0.3984\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[9], line 87\u001b[0m\n\u001b[0;32m     84\u001b[0m     torch\u001b[38;5;241m.\u001b[39msave(model\u001b[38;5;241m.\u001b[39mstate_dict(), \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmnist_fnn_model.pth\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m     86\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[1;32m---> 87\u001b[0m     main()\n",
      "Cell \u001b[1;32mIn[9], line 76\u001b[0m, in \u001b[0;36mmain\u001b[1;34m()\u001b[0m\n\u001b[0;32m     74\u001b[0m optimizer \u001b[38;5;241m=\u001b[39m optim\u001b[38;5;241m.\u001b[39mAdam(model\u001b[38;5;241m.\u001b[39mparameters(), lr\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.001\u001b[39m)\n\u001b[0;32m     75\u001b[0m criterion \u001b[38;5;241m=\u001b[39m nn\u001b[38;5;241m.\u001b[39mCrossEntropyLoss()\n\u001b[1;32m---> 76\u001b[0m train_losses \u001b[38;5;241m=\u001b[39m train_model(model, trainloader, \u001b[38;5;241m5\u001b[39m, optimizer, criterion)\n\u001b[0;32m     77\u001b[0m plt\u001b[38;5;241m.\u001b[39mplot(\u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m6\u001b[39m), train_losses)\n\u001b[0;32m     78\u001b[0m plt\u001b[38;5;241m.\u001b[39mxlabel(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mEpoch\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "Cell \u001b[1;32mIn[9], line 40\u001b[0m, in \u001b[0;36mtrain_model\u001b[1;34m(model, trainloader, epochs, optimizer, criterion)\u001b[0m\n\u001b[0;32m     38\u001b[0m model\u001b[38;5;241m.\u001b[39mtrain()\n\u001b[0;32m     39\u001b[0m running_loss \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.0\u001b[39m\n\u001b[1;32m---> 40\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m images, labels \u001b[38;5;129;01min\u001b[39;00m trainloader:\n\u001b[0;32m     41\u001b[0m     optimizer\u001b[38;5;241m.\u001b[39mzero_grad()\n\u001b[0;32m     42\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m model(images)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:631\u001b[0m, in \u001b[0;36m_BaseDataLoaderIter.__next__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    628\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sampler_iter \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    629\u001b[0m     \u001b[38;5;66;03m# TODO(https://github.com/pytorch/pytorch/issues/76750)\u001b[39;00m\n\u001b[0;32m    630\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reset()  \u001b[38;5;66;03m# type: ignore[call-arg]\u001b[39;00m\n\u001b[1;32m--> 631\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_next_data()\n\u001b[0;32m    632\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m    633\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_kind \u001b[38;5;241m==\u001b[39m _DatasetKind\u001b[38;5;241m.\u001b[39mIterable \u001b[38;5;129;01mand\u001b[39;00m \\\n\u001b[0;32m    634\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \\\n\u001b[0;32m    635\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called:\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:675\u001b[0m, in \u001b[0;36m_SingleProcessDataLoaderIter._next_data\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    673\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_next_data\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m    674\u001b[0m     index \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_next_index()  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[1;32m--> 675\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_fetcher\u001b[38;5;241m.\u001b[39mfetch(index)  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[0;32m    676\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pin_memory:\n\u001b[0;32m    677\u001b[0m         data \u001b[38;5;241m=\u001b[39m _utils\u001b[38;5;241m.\u001b[39mpin_memory\u001b[38;5;241m.\u001b[39mpin_memory(data, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pin_memory_device)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torch\\utils\\data\\_utils\\fetch.py:51\u001b[0m, in \u001b[0;36m_MapDatasetFetcher.fetch\u001b[1;34m(self, possibly_batched_index)\u001b[0m\n\u001b[0;32m     49\u001b[0m         data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset\u001b[38;5;241m.\u001b[39m__getitems__(possibly_batched_index)\n\u001b[0;32m     50\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m---> 51\u001b[0m         data \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset[idx] \u001b[38;5;28;01mfor\u001b[39;00m idx \u001b[38;5;129;01min\u001b[39;00m possibly_batched_index]\n\u001b[0;32m     52\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m     53\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset[possibly_batched_index]\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\datasets\\mnist.py:146\u001b[0m, in \u001b[0;36mMNIST.__getitem__\u001b[1;34m(self, index)\u001b[0m\n\u001b[0;32m    143\u001b[0m img \u001b[38;5;241m=\u001b[39m Image\u001b[38;5;241m.\u001b[39mfromarray(img\u001b[38;5;241m.\u001b[39mnumpy(), mode\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mL\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m    145\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 146\u001b[0m     img \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform(img)\n\u001b[0;32m    148\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtarget_transform \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    149\u001b[0m     target \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtarget_transform(target)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\transforms.py:95\u001b[0m, in \u001b[0;36mCompose.__call__\u001b[1;34m(self, img)\u001b[0m\n\u001b[0;32m     93\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, img):\n\u001b[0;32m     94\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransforms:\n\u001b[1;32m---> 95\u001b[0m         img \u001b[38;5;241m=\u001b[39m t(img)\n\u001b[0;32m     96\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m img\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\transforms.py:137\u001b[0m, in \u001b[0;36mToTensor.__call__\u001b[1;34m(self, pic)\u001b[0m\n\u001b[0;32m    129\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, pic):\n\u001b[0;32m    130\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    131\u001b[0m \u001b[38;5;124;03m    Args:\u001b[39;00m\n\u001b[0;32m    132\u001b[0m \u001b[38;5;124;03m        pic (PIL Image or numpy.ndarray): Image to be converted to tensor.\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    135\u001b[0m \u001b[38;5;124;03m        Tensor: Converted image.\u001b[39;00m\n\u001b[0;32m    136\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[1;32m--> 137\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m F\u001b[38;5;241m.\u001b[39mto_tensor(pic)\n",
      "File \u001b[1;32mD:\\anaconda3\\envs\\wy\\Lib\\site-packages\\torchvision\\transforms\\functional.py:176\u001b[0m, in \u001b[0;36mto_tensor\u001b[1;34m(pic)\u001b[0m\n\u001b[0;32m    174\u001b[0m img \u001b[38;5;241m=\u001b[39m img\u001b[38;5;241m.\u001b[39mpermute((\u001b[38;5;241m2\u001b[39m, \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m))\u001b[38;5;241m.\u001b[39mcontiguous()\n\u001b[0;32m    175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(img, torch\u001b[38;5;241m.\u001b[39mByteTensor):\n\u001b[1;32m--> 176\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m img\u001b[38;5;241m.\u001b[39mto(dtype\u001b[38;5;241m=\u001b[39mdefault_float_dtype)\u001b[38;5;241m.\u001b[39mdiv(\u001b[38;5;241m255\u001b[39m)\n\u001b[0;32m    177\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    178\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m img\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "class MNISTDataLoader:\n",
    "    def __init__(self, batch_size=64):\n",
    "        self.transform = transforms.Compose([\n",
    "            transforms.ToTensor(),\n",
    "            transforms.Normalize((0.5,), (0.5,))\n",
    "        ])\n",
    "        self.trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=self.transform)\n",
    "        self.testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=self.transform)\n",
    "        self.trainloader = torch.utils.data.DataLoader(self.trainset, batch_size=batch_size, shuffle=True)\n",
    "        self.testloader = torch.utils.data.DataLoader(self.testset, batch_size=batch_size, shuffle=False)\n",
    "\n",
    "class FullyConnectedNet(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, output_size):\n",
    "        super(FullyConnectedNet, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.fc2 = nn.Linear(hidden_size, output_size)\n",
    "        self.relu = nn.ReLU()\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = x.view(x.size(0), -1)  # Flatten the input\n",
    "        x = self.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n",
    "class Trainer:\n",
    "    def __init__(self, model, optimizer, criterion):\n",
    "        self.model = model\n",
    "        self.optimizer = optimizer\n",
    "        self.criterion = criterion\n",
    "\n",
    "    def train(self, trainloader, epochs):\n",
    "        train_losses = []\n",
    "        for epoch in range(epochs):\n",
    "            self.model.train()\n",
    "            running_loss = 0.0\n",
    "            for images, labels in trainloader:\n",
    "                self.optimizer.zero_grad()\n",
    "                outputs = self.model(images)\n",
    "                loss = self.criterion(outputs, labels)\n",
    "                loss.backward()\n",
    "                self.optimizer.step()\n",
    "                running_loss += loss.item()\n",
    "            train_losses.append(running_loss / len(trainloader))\n",
    "            print(f'Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(trainloader):.4f}')\n",
    "        return train_losses\n",
    "\n",
    "class Tester:\n",
    "    @staticmethod\n",
    "    def test_and_show_images(model, testloader):\n",
    "        model.eval()\n",
    "        correct = 0\n",
    "        total = 0\n",
    "        fig = plt.figure(figsize=(8, 8))\n",
    "        dataiter = iter(testloader)\n",
    "        images, labels = next(dataiter)\n",
    "        for idx in range(6):\n",
    "            ax = fig.add_subplot(2, 3, idx + 1)\n",
    "            ax.imshow(images[idx].numpy().squeeze(), cmap='gray')\n",
    "            ax.set_title(f'Label: {labels[idx].item()}')\n",
    "            ax.axis('off')\n",
    "        plt.savefig('sample_test_images.png')\n",
    "        plt.show()\n",
    "\n",
    "class Plotter:\n",
    "    @staticmethod\n",
    "    def plot_train_loss(train_losses):\n",
    "        plt.plot(range(1, len(train_losses) + 1), train_losses)\n",
    "        plt.xlabel('Epoch')\n",
    "        plt.ylabel('Loss')\n",
    "        plt.title('Training Loss Curve')\n",
    "        plt.savefig('training_loss_curve.png')\n",
    "        plt.show()\n",
    "\n",
    "class ModelSaver:\n",
    "    @staticmethod\n",
    "    def save_model(model, path='mnist_fnn_model.pth'):\n",
    "        torch.save(model.state_dict(), path)\n",
    "\n",
    "def main():\n",
    "    data_loader = MNISTDataLoader()\n",
    "    input_size = 28 * 28\n",
    "    hidden_size = 128\n",
    "    output_size = 10\n",
    "    model = FullyConnectedNet(input_size, hidden_size, output_size)\n",
    "    optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
    "    criterion = nn.CrossEntropyLoss()\n",
    "    trainer = Trainer(model, optimizer, criterion)\n",
    "    train_losses = trainer.train(data_loader.trainloader, 5)\n",
    "    Plotter.plot_train_loss(train_losses)\n",
    "    Tester.test_and_show_images(model, data_loader.testloader)\n",
    "    ModelSaver.save_model(model)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef1159e7-0fc5-4e3c-b394-fa75f10aeb7c",
   "metadata": {},
   "source": [
    "# 实验十一"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26a789e6-cbf2-42ec-a6a0-b64cfd3584e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torchvision import models, transforms\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "class CustomDataset(Dataset):\n",
    "    def __init__(self, num_samples, image_size, num_classes, transform=None):\n",
    "        self.data = np.random.rand(num_samples, image_size, image_size, 3).astype(np.float32)\n",
    "        self.labels = np.random.randint(0, num_classes, num_samples)\n",
    "        self.transform = transform\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.data)\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        image, label = self.data[idx], self.labels[idx]\n",
    "        if self.transform:\n",
    "            image = self.transform(image)\n",
    "        return image, label\n",
    "\n",
    "class ModifiedResNet(nn.Module):\n",
    "    def __init__(self, num_classes):\n",
    "        super(ModifiedResNet, self).__init__()\n",
    "        self.model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)\n",
    "        self.model.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)\n",
    "        self.model.fc = nn.Linear(self.model.fc.in_features, num_classes)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "\n",
    "class Trainer:\n",
    "    def __init__(self, model, criterion, optimizer):\n",
    "        self.model = model\n",
    "        self.criterion = criterion\n",
    "        self.optimizer = optimizer\n",
    "\n",
    "    def train_epoch(self, train_loader):\n",
    "        self.model.train()\n",
    "        running_loss = 0.0\n",
    "        for images, labels in train_loader:\n",
    "            self.optimizer.zero_grad()\n",
    "            outputs = self.model(images)\n",
    "            loss = self.criterion(outputs, labels.long())\n",
    "            loss.backward()\n",
    "            self.optimizer.step()\n",
    "            running_loss += loss.item()\n",
    "        return running_loss / len(train_loader)\n",
    "\n",
    "class Evaluator:\n",
    "    def __init__(self, model):\n",
    "        self.model = model\n",
    "\n",
    "    def test_epoch(self, test_loader):\n",
    "        self.model.eval()\n",
    "        correct = 0\n",
    "        total = 0\n",
    "        with torch.no_grad():\n",
    "            for images, labels in test_loader:\n",
    "                outputs = self.model(images)\n",
    "                _, predicted = torch.max(outputs.data, 1)\n",
    "                total += labels.size(0)\n",
    "                correct += (predicted == labels).sum().item()\n",
    "        return 100 * correct / total\n",
    "\n",
    "class Plotter:\n",
    "    @staticmethod\n",
    "    def plot_metrics(train_losses, test_accuracies):\n",
    "        plt.figure(figsize=(12, 4))\n",
    "        plt.subplot(1, 2, 1)\n",
    "        plt.plot(train_losses, label='Training Loss')\n",
    "        plt.xlabel('Epoch')\n",
    "        plt.ylabel('Loss')\n",
    "        plt.title('Training Loss Curve')\n",
    "        plt.legend()\n",
    "\n",
    "        plt.subplot(1, 2, 2)\n",
    "        plt.plot(test_accuracies, label='Test Accuracy')\n",
    "        plt.xlabel('Epoch')\n",
    "        plt.ylabel('Accuracy')\n",
    "        plt.title('Test Accuracy Curve')\n",
    "        plt.legend()\n",
    "\n",
    "        plt.savefig('training_loss_and_test_accuracy_curve.png')\n",
    "        plt.show()\n",
    "\n",
    "class ModelSaver:\n",
    "    @staticmethod\n",
    "    def save_model(model, path='custom_resnet_model.pth'):\n",
    "        torch.save(model.state_dict(), path)\n",
    "\n",
    "def main():\n",
    "    num_samples = 1000\n",
    "    image_size = 64\n",
    "    num_classes = 10\n",
    "    transform = transforms.Compose([\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])\n",
    "    ])\n",
    "\n",
    "    train_dataset = CustomDataset(num_samples, image_size, num_classes, transform)\n",
    "    test_dataset = CustomDataset(num_samples, image_size, num_classes, transform)\n",
    "\n",
    "    train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n",
    "    test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n",
    "\n",
    "    model = ModifiedResNet(num_classes)\n",
    "    criterion = nn.CrossEntropyLoss()\n",
    "    optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "    trainer = Trainer(model, criterion, optimizer)\n",
    "    evaluator = Evaluator(model)\n",
    "\n",
    "    num_epochs = 5\n",
    "    train_losses = []\n",
    "    test_accuracies = []\n",
    "\n",
    "    for epoch in range(num_epochs):\n",
    "        loss = trainer.train_epoch(train_loader)\n",
    "        train_losses.append(loss)\n",
    "        accuracy = evaluator.test_epoch(test_loader)\n",
    "        test_accuracies.append(accuracy)\n",
    "        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss:.4f}, Accuracy: {accuracy:.2f}%')\n",
    "\n",
    "    Plotter.plot_metrics(train_losses, test_accuracies)\n",
    "    ModelSaver.save_model(model)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "301a4bd5-2110-4663-a053-2383de740c39",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
